反射让你在运行时动态获取类的信息(字段、方法、构造方法),并调用它们。框架(如 Spring)大量使用反射。
1. 获取 Class 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Person { private String name; public int age;
public Person() {}
public Person(String name, int age) { this.name = name; this.age = age; }
public void sayHello() { System.out.println("你好,我是" + name); }
private void secret() { System.out.println("这是私有方法"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class GetClassDemo { public static void main(String[] args) throws Exception { Class<?> cls1 = Person.class;
Person p = new Person(); Class<?> cls2 = p.getClass();
Class<?> cls3 = Class.forName("Person");
System.out.println(cls1 == cls2); System.out.println(cls1 == cls3); } }
|
2. 获取类的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.lang.reflect.Field; import java.lang.reflect.Method;
public class ClassInfoDemo { public static void main(String[] args) { Class<?> cls = Person.class;
System.out.println(cls.getName()); System.out.println(cls.getSimpleName());
System.out.println("--- 字段 ---"); for (Field f : cls.getDeclaredFields()) { System.out.println(f.getName() + " : " + f.getType().getSimpleName()); }
System.out.println("--- 方法 ---"); for (Method m : cls.getDeclaredMethods()) { System.out.println(m.getName()); } } }
|
3. 动态创建对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.lang.reflect.Constructor;
public class CreateObjectDemo { public static void main(String[] args) throws Exception { Class<?> cls = Person.class;
Constructor<?> ctor1 = cls.getConstructor(); Object obj1 = ctor1.newInstance();
Constructor<?> ctor2 = cls.getConstructor(String.class, int.class); Object obj2 = ctor2.newInstance("小明", 18);
Person p = (Person) obj2; p.sayHello(); } }
|
4. 调用方法
1 2 3 4 5 6 7 8 9 10 11 12
| import java.lang.reflect.Method;
public class InvokeDemo { public static void main(String[] args) throws Exception { Person p = new Person("小红", 20); Class<?> cls = p.getClass();
Method method = cls.getMethod("sayHello"); method.invoke(p); } }
|
5. 访问私有字段和方法
用 setAccessible(true) 可以绕过 private 限制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import java.lang.reflect.Field; import java.lang.reflect.Method;
public class PrivateAccessDemo { public static void main(String[] args) throws Exception { Person p = new Person("小明", 18); Class<?> cls = p.getClass();
Field nameField = cls.getDeclaredField("name"); nameField.setAccessible(true); System.out.println(nameField.get(p));
nameField.set(p, "改名了"); System.out.println(nameField.get(p));
Method secretMethod = cls.getDeclaredMethod("secret"); secretMethod.setAccessible(true); secretMethod.invoke(p); } }
|
6. 反射的应用场景
- 框架:Spring、MyBatis 等框架靠反射自动创建对象、注入依赖
- 注解处理:运行时读取注解信息
- 动态代理:生成代理类
- 序列化:自动读写对象的字段
小结
Class 对象三种获取方式:.class、.getClass()、Class.forName
getDeclaredFields() / getDeclaredMethods() 获取成员
newInstance() 创建对象,invoke() 调用方法
setAccessible(true) 可访问私有成员