必须用getDeclaredConstructor()获取私有构造器并调用setAccessible(true),否则因访问限制或类型不匹配抛异常;反射实例化会跳过静态初始化,导致static final字段为null或默认值。

必须用 getDeclaredConstructor(),getConstructor() 会直接失败
私有构造器根本不会被 getConstructor() 返回——它只查 public 构造器,连 private 的影子都看不到。一调就抛 NoSuchMethodException。真正能“看见”私有构造器的只有 getDeclaredConstructor(),因为它返回本类**声明的所有**构造器(含 private、protected、package-private)。但注意:「看见」不等于「能用」,这步只是拿到引用。
setAccessible(true) 不是可选项,是强制前提
拿到 Constructor 对象后直接调 newInstance(),JVM 会在运行时拦截并抛 IllegalAccessException。Java 的访问检查机制默认生效,必须显式调用 setAccessible(true) 才能绕过。Java 9+ 模块系统下还可能触发 InaccessibleObjectException,尤其在使用 --illegal-access=deny 启动参数时。这不是警告,是硬性门槛。
参数类型必须严格匹配,否则 NoSuchMethodException 再次出现
传给 getDeclaredConstructor() 的 Class 类型数组,必须和目标私有构造器签名完全一致。比如构造器是 private Person(String name, int age),就得写 getDeclaredConstructor(String.class, int.class)。写成 Integer.class 或漏掉一个参数,都会报错。常见疏忽是基本类型和包装类混用(int vs Integer),JVM 不自动装箱。
实例化后字段可能未初始化,特别是 private static final
反射创建的对象,跳过了正常类加载流程中的静态初始化块和 static final 字段赋值逻辑。如果类里有类似 private static final List<string> CONFIG = initConfig();</string> 这种依赖静态方法初始化的字段,反射出来的实例中该字段仍是 null 或默认值(0、false)。这不是 bug,是反射绕过 JVM 初始化阶段的必然结果。别指望它和 new 出来的对象行为完全一致。










