Java反射(Reflection)教程
1. 反射简介
Java反射机制允许程序在运行时动态获取类的信息,并可访问类的构造方法、字段、方法等。反射广泛应用于框架开发、依赖注入、序列化以及动态代理。
核心特点:
- 可以动态加载类
- 可以访问类的私有成员
- 可以在运行时实例化对象、调用方法
2. 获取Class对象
反射的第一步是获取目标类的Class
对象:
1 2 3 4 5 6 7 8 9
| Class<String> clazz1 = String.class;
String str = "hello"; Class<?> clazz2 = str.getClass();
Class<?> clazz3 = Class.forName("java.lang.String");
|
3. 获取构造方法并实例化对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import java.lang.reflect.Constructor;
class Person { private String name; public Person(String name) { this.name = name; } public void sayHello() { System.out.println("Hello, " + name); } }
public class ReflectionExample { public static void main(String[] args) throws Exception { Class<Person> clazz = Person.class; Constructor<Person> constructor = clazz.getConstructor(String.class); Person p = constructor.newInstance("张三"); p.sayHello(); } }
|
4. 访问字段(Field)
可以通过反射访问类的字段,包括私有字段:
1 2 3 4 5 6
| import java.lang.reflect.Field;
Field field = clazz.getDeclaredField("name"); field.setAccessible(true); field.set(p, "李四"); System.out.println(field.get(p));
|
5. 调用方法(Method)
通过反射获取方法并调用:
1 2 3 4
| import java.lang.reflect.Method;
Method method = clazz.getMethod("sayHello"); method.invoke(p);
|
对于私有方法,使用getDeclaredMethod
并设置setAccessible(true)
。
6. 获取类的元数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Method[] methods = clazz.getMethods(); for(Method m : methods) { System.out.println(m.getName()); }
Field[] fields = clazz.getDeclaredFields(); for(Field f : fields) { System.out.println(f.getName()); }
Class<?> superClass = clazz.getSuperclass(); System.out.println(superClass.getName());
|
7. 注意事项
- 性能开销:反射会绕过编译期检查,运行效率较低,不适合高频调用场景。
- 安全性:反射可访问私有成员,需注意安全风险。
- 泛型信息:反射获取的类信息是原始类型,泛型信息会被擦除。
8. 总结
Java反射提供了强大的运行时动态操作能力,使程序在运行时可以分析类结构、动态调用方法和操作对象。它是许多Java框架(如Spring、MyBatis)底层实现的基础,但在使用时需注意性能和安全性。