Java 反射
Java 反射是指在运行时动态地获取一个类的信息(包括类名、属性、方法、构造方法等),并且可以在运行时候动态地创建对象、调用成员方法等。
Java 反射提供了程序在运行时,通过动态获取程序类的相关信息实现的一种机制。使用 Java 反射机制可以通过类名、方法名等信息来动态获取或修改相关数据,可以大大提高程序代码的灵活性和扩展性。Java 反射主要包括以下内容:
- 获取 Java 类的信息。
- 获取 Java 对象的信息。
- 动态创建 Java 对象。
- 动态调用 Java 对象的方法。
获取 Java 类的信息
Java 类的信息主要包括以下几方面:类名、修饰符、父类、接口、属性、方法、构造方法等。通过 Java 反射机制,可以通过类名动态地获取一个 Class 类型的实例,然后通过这个实例获取该类的相关信息。
获取 Class 对象
在 Java 中,每个类的定义都会在编译时由编译器生成一个对应的 Class 对象,用于描述该类的信息。获取 Class 对象的方式有以下三种:
1. 通过类名获取
通过类的全限定名调用 Class 类的 forName() 静态方法来获取该类对应的 Class 对象。
Class<?> cls = Class.forName("com.example.MyClass");
2. 通过对象实例获取
使用对象的 getClass() 方法获取该对象对应的 Class 对象。
MyClass myClass = new MyClass();
Class<? extends MyClass> cls = myClass.getClass();
3. 通过 .class 文件获取
使用类名.class 的方式获取该类对应的 Class 对象。
Class<MyClass> cls = MyClass.class;
获取类名和修饰符
通过 Class 对象的 getName() 和 getModifiers() 方法获取类的全限定名和修饰符。
Class<?> cls = Class.forName("com.example.MyClass");
System.out.println("Class name: " + cls.getName());
System.out.println("Modifiers: " + Modifier.toString(cls.getModifiers()));
输出结果如下:
Class name: com.example.MyClass
Modifiers: public
获取父类和接口
使用 Class 对象的 getSuperclass() 和 getInterfaces() 方法获取该类的父类和实现的接口。
Class<?> cls = Class.forName("com.example.MyClass");
System.out.println("Superclass: " + cls.getSuperclass().getName());
Class<?>[] interfaces = cls.getInterfaces();
for (Class<?> inter : interfaces) {
System.out.println("Interface: " + inter.getName());
}
输出结果如下:
Superclass: java.lang.Object
获取属性
使用 Class 对象的 getFields()、getDeclaredFields() 方法获取该类声明的属性。getFields() 方法返回的是所有 public 的属性,包括父类的属性,而 getDeclaredFields() 方法返回的是所有属性,不包括父类的属性。
Class<?> cls = Class.forName("com.example.MyClass");
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.println("Field: " + field.getName());
}
输出结果如下:
Field: age
Field: name
获取方法
使用 Class 对象的 getMethods()、getDeclaredMethods() 方法获取该类声明的方法。getMethods() 方法返回的是所有 public 的方法,包括父类的方法,而 getDeclaredMethods() 方法返回的是所有方法,不包括父类的方法。同时,通过 getMethod() 方法还可以获取指定的方法。
Class<?> cls = Class.forName("com.example.MyClass");
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
System.out.println("Method: " + method.getName());
}
输出结果如下:
Method: getName
Method: getAge
Method: setName
Method: setAge
获取构造方法
使用 Class 对象的 getConstructors()、getDeclaredConstructors() 方法获取该类声明的构造方法。getConstructors() 方法返回的是所有 public 的构造方法,而 getDeclaredConstructors() 方法返回的是所有构造方法。
Class<?> cls = Class.forName("com.example.MyClass");
Constructor<?>[] constructors = cls.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("Constructor: " + constructor.getName());
}
输出结果如下:
Constructor: com.example.MyClass
Constructor: com.example.MyClass
获取 Java 对象的信息
获取 Java 对象的信息主要包括以下几方面:类名、属性、方法、构造方法等。通过 Java 反射机制,可以通过对象实例获取该对象的相关信息。
获取类名
使用 Object 对象的 getClass() 方法获取该对象的 Class 对象,再调用 getName() 方法获取该对象的类名。
MyClass myClass = new MyClass();
String className = myClass.getClass().getName();
System.out.println("Class name: " + className);
输出结果如下:
Class name: com.example.MyClass
获取属性值
使用 Field 对象的 get() 和 set() 方法获取和设置对象的属性值。
MyClass myClass = new MyClass();
Field field = myClass.getClass().getDeclaredField("name");
field.setAccessible(true);
String name = (String) field.get(myClass);
field.set(myClass, "Lucy");
调用方法
使用 Method 对象的 invoke() 方法调用对象的方法。
MyClass myClass = new MyClass();
Method method = myClass.getClass().getMethod("getName");
String name = (String) method.invoke(myClass);
调用构造方法
使用 Constructor 对象的 newInstance() 方法调用对象的构造方法。
Class<?> cls = Class.forName("com.example.MyClass");
Constructor<?> constructor = cls.getDeclaredConstructor(String.class, int.class);
MyClass myClass = (MyClass) constructor.newInstance("Tom", 22);
动态创建 Java 对象
在 Java 中,通过反射技术可以在运行时创建一个类的实例。具体步骤如下:
- 获取要创建对象的 Class 对象。
- 调用 Class 对象的 newInstance() 方法创建对象。
- 在创建对象时需要注意,如果类的无参构造方法被禁止,则需要通过调用该类的有参构造方法来创建对象。
Class<?> cls = Class.forName("com.example.MyClass");
MyClass myClass = (MyClass) cls.newInstance();
动态调用 Java 对象的方法
在 Java 中,通过反射技术可以在运行时动态调用一个对象的方法。具体步骤如下:
- 获取要调用方法对应的 Method 对象。
- 调用 Method 对象的 invoke() 方法调用方法。
- 在调用方法时需要注意参数的类型和数量。
MyClass myClass = new MyClass();
Method method = myClass.getClass().getMethod("setName", String.class);
method.invoke(myClass, "Tom");
总结
Java 反射机制可以让程序在运行时动态地获取类的属性信息、方法、构造方法、父类、接口等信息,并且可以通过反射机制动态地创建对象、调用对象的方法。反射机制在 Java 开发中有广泛的应用,比如框架、ORM 映射等,也可以用于编写 Java 的测试代码。但是由于反射机制的类型检查变得不安全,也会影响程序运行效率,因此在使用时需要谨慎操作。
关注微信公众号:“小虎哥的技术博客”。我们会定期发布关于Java技术的详尽文章,让您能够深入了解该领域的各种技巧和方法,让我们一起成为更优秀的程序员👩💻👨💻!