Nutz 的 Mirror 将 Java 反射中常见的类型、字段、方法和对象创建封装起来。理解这层封装,可以看清框架怎样把外部数据映射到对象,但不能把它理解成绕过所有访问限制的能力。本文基于 1.b.53。
取字段和调用 getter 的语义不同
通过 Method 调用 getter,可能触发业务计算、懒加载或其他副作用;通过 Field 取值则读取具体字段,但要处理声明类、继承和访问权限。两者都能“获得属性”,不代表结果与行为总是一样。
Mirror 的价值在于集中处理这些重复查询与类型判断。阅读时应跟到最终使用的是 Method.invoke、Field.get 还是其他入口,再判断封装带来的默认行为。
注解查找要看继承规则
1.b.53 的 Mirror.getAnnotation 会沿父类方向查找指定注解,但这不是所有反射 API 都具有的递归行为。接口、方法、字段和类上的注解规则也不同;运行时读取还要求适当的 Retention。
不要因为一个类上找到了注解,就认定它的全部成员也继承相同语义。框架如何合并父子配置,需要看自己的查找和覆盖顺序。
对象创建的几个入口
ArrayBorning 通过反射创建指定类型和长度的数组,引用数组初始元素为 null,不会顺便为每个位置实例化一个对象。基本类型数组则使用对应默认值。
ConstructorBorning 保存 Constructor,并通过 Constructor.newInstance(args) 创建对象,不是调用 Class.newInstance。构造函数内部抛出的异常会经过 InvocationTargetException,封装层需要保留真实原因。
该版本尝试设置可访问标志;在后续 JDK 模块强封装等环境中,这种访问可能受限制。异常时要检查目标构造函数、参数和运行权限,不能仅靠 setAccessible 就保证兼容。
反射让框架能在运行时检查和创建对象,同时引入类型转换、性能与可维护性成本。优先理解调用边界,再考虑缓存和优化。