课程导言:看不见的力量
"反射是Java的X光透视——它让你看到类的内部结构,甚至操作私有成员,就像拥有了超能力。"
反射的日常类比
类如蓝图:普通方式只能按蓝图建房(创建对象)
反射如施工队:能查看蓝图细节(类结构),甚至修改未公开部分(私有成员)
Ⅰ. 反射基础:Class对象入口
1.1 获取Class对象的三种方式
// 1. 类名.class (最安全,编译时检查)Class<String> stringClass = String.class;// 2. 对象.getClass() (已有对象实例时)String s = "Hello";Class<?> strClass = s.getClass();// 3. Class.forName() (动态加载,可能抛出ClassNotFoundException)Class<?> arrayListClass = Class.forName("java.util.ArrayList");
1.2 基本类型与数组的Class
Class<Integer> intClass = int.class; // 注意:不是Integer.classClass<int[]> intArrayClass = int[].class;Class<String[][]> twoDStringArrayClass = String[][].class;
Ⅱ. 深入类结构:解剖Java类
2.1 获取类信息
Class<ArrayList> arrayListClass = ArrayList.class;// 获取类名String className = arrayListClass.getName(); // java.util.ArrayListString simpleName = arrayListClass.getSimpleName(); // ArrayList// 获取修饰符int modifiers = arrayListClass.getModifiers();boolean isPublic = Modifier.isPublic(modifiers);boolean isAbstract = Modifier.isAbstract(modifiers);// 获取父类Class<?> superClass = arrayListClass.getSuperclass(); // AbstractList// 获取接口Class<?>[] interfaces = arrayListClass.getInterfaces(); // [List, RandomAccess, ...]
2.2 字段操作:查看与修改
class Person {private String name;public int age;}// 获取字段Field[] fields = Person.class.getDeclaredFields(); // 获取所有字段(包括私有)Field nameField = Person.class.getDeclaredField("name"); // 获取指定字段// 访问私有字段(突破封装!)Person p = new Person();nameField.setAccessible(true); // 关键步骤:关闭访问检查nameField.set(p, "Alice"); // 设置字段值String nameValue = (String) nameField.get(p); // "Alice"
2.3 方法操作:调用任意方法
class Calculator {private int add(int a, int b) {return a + b;}}// 获取方法Method addMethod = Calculator.class.getDeclaredMethod("add", int.class, int.class);// 调用私有方法Calculator calc = new Calculator();addMethod.setAccessible(true);int result = (int) addMethod.invoke(calc, 5, 3); // 8
Ⅲ. 构造对象:超越new关键字
3.1 使用构造器创建实例
// 获取构造器Constructor<String> stringConstructor = String.class.getConstructor(String.class);// 创建实例String str = stringConstructor.newInstance("Hello Reflection");System.out.println(str); // "Hello Reflection"
3.2 突破单例限制(演示,慎用)
class Singleton {private static Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}}// 反射攻击单例Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();constructor.setAccessible(true);Singleton newInstance = constructor.newInstance(); // 创建新实例,破坏单例
Ⅳ. 反射与泛型:保留类型信息
4.1 获取泛型类型
class GenericClass<T> {private List<String> stringList = new ArrayList<>();public List<T> getData() {return new ArrayList<>();}}// 获取字段的泛型类型Field stringListField = GenericClass.class.getDeclaredField("stringList");Type genericType = stringListField.getGenericType(); // java.util.List<java.lang.String>// 获取方法的泛型返回类型Method getDataMethod = GenericClass.class.getMethod("getData");Type returnType = getDataMethod.getGenericReturnType(); // java.util.List<T>
Ⅴ. 反射实战:框架设计核心
5.1 简易依赖注入容器
class DIContainer {private Map<Class<?>, Object> instances = new HashMap<>();public void register(Class<?> clazz) throws Exception {Constructor<?> constructor = clazz.getDeclaredConstructor();constructor.setAccessible(true);instances.put(clazz, constructor.newInstance());}public <T> T resolve(Class<T> clazz) {return clazz.cast(instances.get(clazz));}}// 使用DIContainer container = new DIContainer();container.register(UserService.class);UserService service = container.resolve(UserService.class);
5.2 注解处理器
@Retention(RetentionPolicy.RUNTIME)@interface Table {String name();}@Table(name = "users")class UserEntity {}// 处理注解Class<UserEntity> entityClass = UserEntity.class;Table tableAnnotation = entityClass.getAnnotation(Table.class);System.out.println("表名: " + tableAnnotation.name()); // "users"
Ⅵ. 反射的代价与安全
6.1 性能考量
// 反射调用 vs 直接调用(性能测试)long start = System.nanoTime();// 直接调用100万次: 约5ms// 反射调用100万次: 约500ms (慢100倍!)
6.2 安全限制
// 安全管理器阻止反射访问System.setSecurityManager(new SecurityManager() {@Overridepublic void checkPermission(Permission perm) {if (perm instanceof ReflectPermission) {throw new SecurityException("反射操作被禁止!");}}});// 尝试访问私有字段将抛出SecurityExceptionField field = String.class.getDeclaredField("value");field.setAccessible(true); // 抛出异常
反射最佳实践:安全使用指南
缓存反射对象:
private static final Field NAME_FIELD;static {try {NAME_FIELD = Person.class.getDeclaredField("name");NAME_FIELD.setAccessible(true);} catch (NoSuchFieldException e) {throw new ExceptionInInitializerError(e);}}
优先接口而非反射:

避免突破封装:仅在框架开发等特殊场景访问私有成员
课程总结:反射的三大能力
内省(Introspection):
查看类结构
获取注解信息
操作(Manipulation):
修改字段值
调用私有方法
动态(Dynamics):
运行时加载类
动态创建对象

课后挑战
对象转Map工具:
public static Map<String, Object> toMap(Object obj) {// 返回对象所有字段名和值的映射(包括私有字段)}
方法调用日志代理:
class LoggingProxy {public static <T> T create(Class<T> interfaceClass, T realObject) {// 返回代理对象,在每次方法调用前后打印日志}}
简易ORM框架:
class MiniORM {public <T> void save(T entity) {// 通过反射读取@Entity注解,生成SQL插入语句}}
下节课预告:《Java注解:元数据的力量》
你将学到:
内置注解与自定义注解
注解的保留策略与目标类型
注解处理器开发
运行时注解与编译时注解
注解在框架中的实战应用
元注解的深度解析
"反射是Java的元编程能力,它赋予你在运行时修改程序行为的力量。但记住:能力越大,责任越大——谨慎使用这把双刃剑!"

文章转载自让天下没有难学的编程,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




