java中可通过getdeclaredconstructor()获取私有构造器并调用setaccessible(true)后使用newinstance()创建实例,但jdk 9+需配合--add-opens等模块开放参数,否则抛illegalaccessexception或inaccessibleobjectexception;newinstance()已弃用,推荐unsafe.allocateinstance作为替代。

可以直接用,但必须配合 setAccessible(true),且 JDK 9+ 需额外处理模块限制;否则会抛 IllegalAccessException 或 InaccessibleObjectException。
获取并解锁私有构造器
用 getDeclaredConstructor() 获取目标构造器(不是 getConstructor()),再调用 setAccessible(true) 关闭语言层访问检查:
- 若构造器带参,需精确传入参数类型,例如
getDeclaredConstructor(String.class, int.class) - 无参构造器直接写
getDeclaredConstructor() -
setAccessible(true)是强制步骤,缺它必报IllegalAccessException - JDK 12+ 在强封装环境下可能仍失败,需配合 JVM 启动参数
JDK 9+ 必须加模块开放参数
仅靠 setAccessible(true) 不够——模块系统会拦截反射穿透。启动时必须显式开放对应包:
- 非模块化项目:加
--add-opens java.base/java.util=ALL-UNNAMED(以ArrayList为例) - 模块化项目:替换
ALL-UNNAMED为你的模块名,如--add-opens java.base/java.time=your.module.name - 多个包需多次指定,不能通配
- 未加参数时,即使
setAccessible(true)成功,newInstance()仍抛异常
正确调用 newInstance 并处理异常
newInstance() 已在 JDK 9 标记为 @Deprecated,但仍是当前主流兼容写法。调用时需捕获四类典型异常:
-
NoSuchMethodException:构造器签名不匹配,检查参数类型顺序 -
InstantiationException:类是抽象类、接口,或构造器本身抛了 unchecked 异常 -
IllegalAccessException:漏掉setAccessible(true)或模块未开放 -
InvocationTargetException:构造器内抛异常,用e.getCause()取原始错误
更底层替代方案:Unsafe.allocateInstance
如果只需对象壳、不执行构造逻辑(比如反序列化、Mock 场景),可用 Unsafe.allocateInstance():
- 完全绕过构造器调用,字段全为默认值(
null/0/false) - 不受模块限制,无需
--add-opens,也不依赖setAccessible - 获取
Unsafe实例需反射读取私有静态字段theUnsafe - 不适用于依赖构造器初始化状态的类,慎用于业务主流程











