应只用Constructor.newInstance(),因Class.newInstance()在Java 9中被弃用、Java 14起彻底移除;前者支持带参构造、突破访问限制、统一异常封装、可缓存提升性能,后者仅限public无参构造且异常处理混乱。

直接说结论:现在应该只用 Constructor.newInstance(),Class.newInstance() 已在 Java 9 中被标记为 @Deprecated,Java 14 起彻底移除。不是“不推荐”,而是“不能用了”。
参数灵活性差异明显
Class.newInstance() 完全不接受任何参数,只能调用无参构造器。哪怕类里有默认构造器(编译器自动生成的 public 无参构造),它也勉强能用;但只要类显式定义了带参构造、又没写无参构造,就会抛 NoSuchMethodException。
Constructor.newInstance() 则按需调用:
- 要调无参构造:用
getConstructor()或getDeclaredConstructor()获取后调用 - 要调带参构造:必须传入对应类型的 Class 数组,比如
getConstructor(String.class, int.class) - 参数类型不匹配会立即报
IllegalArgumentException: argument type mismatch
访问权限控制能力不同
Class.newInstance() 只认 public 构造器,private、protected、包级私有的一律拒绝,连尝试都不给。
Constructor.newInstance() 配合 setAccessible(true) 可突破访问限制:
- 对 private 构造器调用前加一句
constructor.setAccessible(true) - 这是 Spring、Jackson 等框架能绕过封装创建 Bean 的关键机制
- 注意:模块化(Java 9+)下可能受
--illegal-access策略影响,需额外配置
异常处理逻辑截然不同
Class.newInstance() 把构造器里抛出的任何异常(包括 RuntimeException 和 SQLException 这类 checked 异常)原样往上扔,调用方得自己捕获一堆可能类型。
Constructor.newInstance() 统一封装为 InvocationTargetException:
- 真实异常藏在
getCause()里,统一一层 try-catch 即可 - 便于框架做统一错误处理和日志追踪
- 这也是主流框架弃用 Class.newInstance() 的核心原因之一
性能与兼容性现实考量
两者都比 new 慢,但 Constructor.newInstance() 更可控:
- 可以缓存 Constructor 对象,避免重复反射查找(Class.newInstance() 每次都要内部查一次)
- 支持泛型类型推导,返回值是
T,不用强转 - 从 Java 9 开始,Class.newInstance() 的 Javadoc 明确写着 “This method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method is discouraged in favor of {@link Constructor#newInstance()}.”

















