Java中的反射是怎么回事?

反射的概念

《Java核心技术》中的定义是这样的:能够分析类能力的程序,就是反射

这就是一个概念,跟java中经常提的问题:对象是什么? 一类问题,简单来说就是将类创建对象的逻辑反过来,由对象获得其所属类型的信息。它允许程序在运行时查询和操作类、方法、字段等信息。

实现原理机制

说到反射就不得不谈一个Class类,就是类的类,存的是各种类的状态信息的类,Java的反射机制主要通过java.lang.Class类来实现。你可以通过Class.forName("类名")方法来获取一个Class对象,进而获取该类的信息。

  • Object 类中的getClass( ) 方法将会返回一个Class 类型的实例。
  • Class类常用的方法。
    • e.getname()获取e的类的名字
    • 静态方法Class.forName(className),返回对应的Class对象。
    • 来动态地创建一个类的实例e.getClass().newInstance();

利用反射获取打印类的信息(也叫能力)

不是通过" . "的形式,获得一个类的方法,属性,等具体信息

java 复制代码
package test729;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;

public class ReflectionTest {
    /**
     * 判断程序启动时是否有命令行参数。如果有,则将第一个参数作为类名;如果没有,则提示用户输入类名并读取用户输入。
     * @param args
     */
    public static void main(String[] args) {
        String className;
        if (args.length > 0) {
            className = args[0];
        } else {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入类名(如:java.util.Date):");
            className = scanner.next();
        }
/**
 *使用 Class.forName(className) 动态加载指定的类。然后获取该类的父类和修饰符。
 * 打印类的修饰符、类名和父类信息。
 * 调用 printConstructors(cl), printMethods(cl), 和 printFields(cl) 方法,分别打印构造函数、方法和字段的信息。
 * 捕捉并处理 ClassNotFoundException 异常,打印异常信息。
 */
        try {
            Class<?> cl = Class.forName(className);
            Class<?> superClass = cl.getSuperclass();
            String modifiers = Modifier.toString(cl.getModifiers());

            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.print("class " + className);
            if (superClass != null && superClass != Object.class) {
                System.out.print(" extends " + superClass.getName());
            }
            System.out.println("\n{");
            printConstructors(cl);
            System.out.println();
            printMethods(cl);
            System.out.println();
            printFields(cl);
            System.out.println("}");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * printConstructors 方法打印类的构造函数信息。
     * 使用 cl.getDeclaredConstructors() 获取所有构造函数。
     * 遍历每个构造函数,获取其修饰符、名称和参数类型。
     * 打印构造函数的修饰符、名称和参数列表。
     * @param cl
     */
    public static void printConstructors(Class<?> cl) {
        Constructor<?>[] constructors = cl.getDeclaredConstructors();
        for (Constructor<?> c : constructors) {
            String name = c.getName();
            String modifiers = Modifier.toString(c.getModifiers());

            System.out.print("  ");
            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.print(name + "(");

            Class<?>[] paramTypes = c.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                if (i > 0) {
                    System.out.print(", ");
                }
                System.out.print(paramTypes[i].getName());
            }
            System.out.println(");");
        }
    }

    /**
     * printMethods 方法打印类的方法信息。
     * 使用 cl.getDeclaredMethods() 获取所有方法。
     * 遍历每个方法,获取其修饰符、返回类型、名称和参数类型。
     * 打印方法的修饰符、返回类型、名称和参数列表。
     * @param cl
     */
    public static void printMethods(Class<?> cl) {
        Method[] methods = cl.getDeclaredMethods();
        for (Method method : methods) {
            Class<?> returnType = method.getReturnType();
            String name = method.getName();
            String modifiers = Modifier.toString(method.getModifiers());

            System.out.print("  ");
            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.print(returnType.getName() + " " + name + "(");

            Class<?>[] paramTypes = method.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                if (i > 0) {
                    System.out.print(", ");
                }
                System.out.print(paramTypes[i].getName());
            }
            System.out.println(");");
        }
    }

    /**
     * printFields 方法打印类的字段信息。
     * 使用 cl.getDeclaredFields() 获取所有字段。
     * 遍历每个字段,获取其修饰符、类型和名称。
     * 打印字段的修饰符、类型和名称。
     * 以上代码整体上实现了动态加载类,并输出类的构造函数、方法和字段的信息。
     * @param cl
     */
    public static void printFields(Class<?> cl) {
        Field[] fields = cl.getDeclaredFields();
        for (Field f : fields) {
            Class<?> type = f.getType();
            String name = f.getName();
            String modifiers = Modifier.toString(f.getModifiers());

            System.out.print("  ");
            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.println(type.getName() + " " + name + ";");
        }
    }
}

这个测试案例可以利用反射打印出一个类的所有信息和属性。

测试输出结果

XML 复制代码
请输入类名(如:java.util.Date):
java.util.Date
public class java.util.Date
{
  public java.util.Date(int, int, int, int, int, int);
  public java.util.Date(java.lang.String);
  public java.util.Date();
  public java.util.Date(long);
  public java.util.Date(int, int, int);
  public java.util.Date(int, int, int, int, int);

  public boolean after(java.util.Date);
  public boolean before(java.util.Date);
  public boolean equals(java.lang.Object);
  public java.lang.String toString();
  public int hashCode();
  public java.lang.Object clone();
  public int compareTo(java.util.Date);
  public volatile int compareTo(java.lang.Object);
  private void readObject(java.io.ObjectInputStream);
  private void writeObject(java.io.ObjectOutputStream);
  private final sun.util.calendar.BaseCalendar$Date normalize(sun.util.calendar.BaseCalendar$Date);
  private final sun.util.calendar.BaseCalendar$Date normalize();
  public static long parse(java.lang.String);
  public static java.util.Date from(java.time.Instant);
  public long getTime();
  public void setTime(long);
  public int getDate();
  public static long UTC(int, int, int, int, int, int);
  private static final java.lang.StringBuilder convertToAbbr(java.lang.StringBuilder, java.lang.String);
  private final sun.util.calendar.BaseCalendar$Date getCalendarDate();
  private static final sun.util.calendar.BaseCalendar getCalendarSystem(int);
  private static final sun.util.calendar.BaseCalendar getCalendarSystem(sun.util.calendar.BaseCalendar$Date);
  private static final sun.util.calendar.BaseCalendar getCalendarSystem(long);
  public int getDay();
  public int getHours();
  private static final synchronized sun.util.calendar.BaseCalendar getJulianCalendar();
  static final long getMillisOf(java.util.Date);
  public int getMinutes();
  public int getMonth();
  public int getSeconds();
  private final long getTimeImpl();
  public int getTimezoneOffset();
  public int getYear();
  public void setDate(int);
  public void setHours(int);
  public void setMinutes(int);
  public void setMonth(int);
  public void setSeconds(int);
  public void setYear(int);
  public java.lang.String toGMTString();
  public java.time.Instant toInstant();
  public java.lang.String toLocaleString();

  private static final sun.util.calendar.BaseCalendar gcal;
  private static sun.util.calendar.BaseCalendar jcal;
  private transient long fastTime;
  private transient sun.util.calendar.BaseCalendar$Date cdate;
  private static int defaultCenturyStart;
  private static final long serialVersionUID;
  private static final [Ljava.lang.String; wtb;
  private static final [I ttb;
}

进程已结束,退出代码为 0
相关推荐
Theodore_10221 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸2 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象3 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了3 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
----云烟----3 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024063 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
小二·3 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic4 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it4 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
懒洋洋大魔王4 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq