java中反射的基本使用
一、参考文档:
- https://www.cnblogs.com/chanshuyi/p/head_first_of_reflection.html
- chat gpt 问答
二、前言
- 反射是 java 的一个特性,是 java 提供的一种机制。
- 反射允许程序在运行时查询和操作类的信息。
- 反射对很多高级功能(框架设计、动态代理等)都很有用。
- 反射提供了很多类和接口来操作class对象,如 java.lang.Class java.lang.reflect.Constructor java.lang.reflect.Method java.lang.reflect.Field
- 反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
三、理论基础:
1. 获取Class对象:
// 方式 1: 使用类的.class 属性
Class<?> clazz = MyClass.class;
// 方式 2: 使用 Class.forName()
Class<?> clazz2 = Class.forName("com.example.MyClass"); //这个字符串可能是一个参数,也就是“在运行时才知道要操作的类是什么”
// 方式3: 使用对象的getClass()方法
MyClass myClass = new MyClass(); Class<?> clazz3 = myClass.getClass();
【注意】先获取反射对象 clazz,后续所有的操作都是用 clazz 来执行的,包括建立对象、获取类的构造器、方法、属性。
2. 获取类的构造函数
// 获取所有构造函数 Constructor<?>[] constructors = clazz.getConstructors(); // 获取指定的构造函数 Constructor<?> constructor = clazz.getConstructor(String.class, int.class); Object obj = constructor.newInstance("John", 30);
3. 创建对象
// 通过无参构造方法创建实例 Constructor<?> constructor = clazz.getConstructor(); Object obj = constructor.newInstance(); // 带参构造函数创建实例 (括号里的两个类型就是下面 newInstance() 里的两个参数类型) Constructor<?> constructor = clazz.getConstructor(String.class, int.class); Object obj = constructor.newInstance("Alice", 30);
4. 获取类的方法
// 获取所有公共方法 Method method = clazz.getMethod("methodName", String.class); // 指定方法名和参数类型 method.invoke(obj, "parameter"); // 获取私有方法 Method privateMethod = clazz.getDeclaredMethod("privateMethod"); privateMethod.setAccessible(true); // 允许访问私有方法 privateMethod.invoke(obj);
5. 获取类的字段
// 获取字段 Field field = clazz.getField("fieldName"); // 获取公共字段 Object fieldValue = field.get(obj); // 获取字段的值 // 访问私有字段 Field privateField = clazz.getDeclaredField("privateField"); privateField.setAccessible(true); // 允许访问私有字段 Object value = privatePrice.get(obj);//获取私有字段的值 privateField.set(obj, "newValue"); // 修改字段的值
四、代码实践:
目录结构如下:

Apple.java
package com.example.reflect; public class Apple { public String color; private int price; public Apple() { } public Apple(String color, int price) { this.color = color; this.price = price; } public void setColor(String color) { this.color = color; } public void setPrice(int price) { this.price = price; } public String getColor() { return color; } public int getPrice() { return price; } }
在Main.java中正常调用
Apple apple = new Apple(); apple.setColor("red"); apple.setPrice(5); System.out.println("---------------- 正常调用 ----------------"); System.out.println("[public] color: " + apple.color); System.out.println("[public] getColor(): " + apple.getColor()); System.out.println("[private] price: "+apple.getPrice());
运行结果:

用反射调用(异常先都直接抛出):
获取class对象:
// 1. 获取class对象 Class<Apple> clazz = Apple.class; Class<?> clz = Class.forName("com.example.reflect.Apple"); System.out.println(clazz); System.out.println(clz);
运行结果:证明两种方法获取的Class类是一样的(没有测试第三种方法)。

获取反射对象 clazz后,后续所有的操作都是用 clazz 来执行的,包括建立对象、获取类/对象的构造器、方法、属性。
用clazz获取类的构造器:只是用clazz来获取,不用clz(为了简化代码)
// 2. 获取构造器 // 2.1 获取空构造器 Constructor<Apple> constructor = clazz.getConstructor(); Apple apple = constructor.newInstance();//创建对象 System.out.println(apple); // 2.2 获取有参构造器 Constructor<Apple> constructor1 = clazz.getConstructor(String.class,int.class ); Apple apple1 = constructor1.newInstance("Green", 2);//创建对象 System.out.println(apple1);
运行结果:可见获取空构造器和有参构造器都成功了。

用clazz创建对象:
在上一步获取构造器中, constructor.newInstance() 和 constructor1.newInstance("Green", 2); 就是创建了对象。
用clazz获取类的方法:以用有参构造器创建对象为例(为了简化代码)
// 4. 获取类的方法 // 4.1 获取有参方法(第一个参数是方法名,第二个参数是setColor(String color) 的类型) Method setColorMethod = clazz.getMethod("setColor", String.class); Method setPriceMethod = clazz.getMethod("setPrice", int.class); // // 4.2 获取无参方法 Method getColorMethod = clazz.getMethod("getColor"); Method getPriceMethod = clazz.getMethod("getPrice"); // 4.1.1 调用有参方法, // .invoke() 就是调用这个方法,第一个参数是要操作的对象,第二个参数是修改的参数值 setColorMethod.invoke(apple, "Yellow"); setPriceMethod.invoke(apple,66); // 4.2.1 调用无参方法 // .invoke() 就是调用这个方法,参数是要操作的对象 Object color = getColorMethod.invoke(apple); Object price = getPriceMethod.invoke(apple); System.out.println("color: "+ color); System.out.println("price: "+ price);
运行结果:apple 从 constructor.newInstance("Green", 2); 变成了 Yellow,66

用clazz获取类的字段:上一步是用 getPrice() 获取price,这一步是直接访问price
Apple.java 中 public String color; private int price; 分别获取一下:
// 5. 获取类的字段 // 5.1 获取字段 Field field = clazz.getField("color");//获取公共字段 Object color = field.get(apple);//获取 apple对象中 字段color的值 System.out.println(color); // 5.2 获取私有字段 Field privateField = clazz.getDeclaredField("price");//注意这里方法变成了 getDeclaredField() privateField.setAccessible(true);//允许访问私有字段,不设置这一句运行会报错 Object price = privateField.get(apple);//获取私有字段的值 System.out.println(price);
运行结果:

main全部代码如下:
package com.example; import com.example.reflect.Apple; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Main { /** * 【正射】未运行时就已经确定了要运行的类 * 【反射】就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。 * * 反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意方法和属性 */ public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException { // 正常调用 // Apple apple = new Apple(); // apple.setColor("red"); // apple.setPrice(5); // System.out.println("---------------- 正常调用 ----------------"); // System.out.println("[public] color: " + apple.color); // System.out.println("[public] getColor(): " + apple.getColor()); // System.out.println("[private] price: "+apple.getPrice()); System.out.println("**********************************"); // 1. 获取class对象 Class<Apple> clazz = Apple.class; // 2. 获取构造器 Constructor<Apple> constructor = clazz.getConstructor(String.class, int.class); // 3. 创建对象 Apple apple = constructor.newInstance("Green", 2); // // 4. 获取类的方法 // // 4.1 获取有参方法(第一个参数是方法名,第二个参数是setColor(String color) 的类型) // Method setColorMethod = clazz.getMethod("setColor", String.class); // Method setPriceMethod = clazz.getMethod("setPrice", int.class); // // // 4.2 获取无参方法 // Method getColorMethod = clazz.getMethod("getColor"); // Method getPriceMethod = clazz.getMethod("getPrice"); // // 4.1.1 调用有参方法, // // .invoke() 就是调用这个方法,第一个参数是要操作的对象,第二个参数是修改的参数值 // setColorMethod.invoke(apple, "Yellow"); // setPriceMethod.invoke(apple,66); // // 4.2.1 调用无参方法 // // .invoke() 就是调用这个方法,参数是要操作的对象 // Object color = getColorMethod.invoke(apple); // Object price = getPriceMethod.invoke(apple); // System.out.println("color: "+ color); // System.out.println("price: "+ price); // 5. 获取类的字段 // 5.1 获取字段 Field field = clazz.getField("color");//获取公共字段 Object color = field.get(apple);//获取 apple对象中 字段color的值 System.out.println(color); // 5.2 获取私有字段 Field privateField = clazz.getDeclaredField("price");//注意这里方法变成了 getDeclaredField() privateField.setAccessible(true);//允许访问私有字段,不设置这一句运行会报错 Object price = privateField.get(apple);//获取私有字段的值 System.out.println(price); } }

浙公网安备 33010602011771号