可通过反射调用私有构造器创建实例,但需满足访问控制解除(getdeclaredconstructor+setaccessible)、参数严格匹配及jdk9+模块兼容(--add-opens或unsafe.allocateinstance),并妥善捕获各类异常。

可以通过反射强制调用私有构造器来创建实例,但需满足访问控制解除、参数匹配和环境兼容三方面条件。JDK 9+ 后限制更严,不能只靠 setAccessible(true) 就生效。
获取并放开私有构造器访问
必须使用 getDeclaredConstructor()(不是 getConstructor()),它能拿到 private/protected/package-private 构造器。接着调用 setAccessible(true) 关闭语言层访问检查:
- 这步必不可少,否则
newInstance()会直接抛IllegalAccessException - 若类在模块化项目中,仅设
setAccessible(true)不够——JDK 9+ 的模块系统会拦截 - 需配合 JVM 启动参数开放模块,例如:
--add-opens java.base/java.lang=ALL-UNNAMED
正确传入构造参数
参数类型必须与目标构造器签名严格一致,JVM 不会自动宽泛匹配:
- 有参构造:如
private Person(String name, int age),要写getDeclaredConstructor(String.class, int.class) - 基本类型可直接传值(如
25),JVM 自动装箱;但 null 值需显式指定类型避免重载歧义 - 无参构造可传
null或空数组,也可不传参数(newInstance()重载支持)
处理 JDK 9+ 的兼容性问题
Constructor.newInstance() 在 JDK 9 起已被标记为 @Deprecated,且模块限制导致传统写法失效:
- 推荐方案:改用
Unsafe.allocateInstance(),它绕过构造逻辑、不执行任何构造器,也不受模块限制 - 替代写法:保留
setAccessible(true) + newInstance(),但必须确保启动时加--add-opens参数 - 注意:
Unsafe创建的对象字段全为默认值(null/0/false),不适用于依赖构造初始化的类
异常捕获要覆盖完整链路
反射调用可能在多个环节失败,应分别处理:
-
NoSuchMethodException:构造器签名写错(类型或数量不匹配) -
InstantiationException:类是抽象类、接口,或没有可用构造器 -
IllegalAccessException:忘了setAccessible(true),或模块未开放 -
InvocationTargetException:构造器内部抛异常,用getCause()获取原始错误











