【问题标题】:Java 9 replace Class.newInstanceJava 9 替换 Class.newInstance
【发布时间】:2019-08-21 21:44:11
【问题描述】:

Class.newInstance 在 Java 9 中已弃用:

clazz.newInstance()

可以替换为

clazz.getDeclaredConstructor().newInstance()

问题是getDeclaredConstructor 返回任何构造函数而不考虑访问级别。

如果我想替换我的代码中的所有出现(在不同的包/访问级别),我应该使用getConstructor 来获取公共构造函数吗?

与指定 parameterTypes 匹配的公共构造函数的 Constructor 对象

或者不能bulk 替换所有出现,因为它需要根据情况(如果存在公共构造函数和/或如果我具有正确的访问级别类)?

编辑

getDeclaredConstructor:

   return getConstructor0(parameterTypes, Member.DECLARED);

获取构造函数:

   return getConstructor0(parameterTypes, Member.PUBLIC);

【问题讨论】:

  • 如果需要访问不同层次的构造函数,getDeclaredConstructor(s)是唯一的出路。你不能使用getDeclaredConstructors​()(不是getDeclaredConstructor())来获取所有构造函数并根据你的逻辑替换一个吗?
  • 正如弃用消息所说,clazz.newInstance() 的等效代码是 clazz.getDeclaredConstructor().newInstance()。我认为这意味着您成功使用clazz.newInstance() 的任何地方都可以替换为推荐的代码。如果您将 clazz.newInstance() 替换为 clazz.getConstructor().newInstance(),您将更改代码的语义。
  • 我没有尝试过,但如果零参数构造函数不公开,我也不希望 clazz.newInstance() 工作——是吗?那么在实践中使用clazz.getDeclaredConstructor().newInstance() 会失去什么?
  • @OleV.V.是的,Class.newInstance() 与非公共构造函数一起使用。但它要求您具有适当的访问权限,否则它会抛出 IllegalAccessException(来自一些快速、非详尽的测试)。
  • 相关(关于它被弃用的原因):stackoverflow.com/questions/195321/…

标签: java reflection constructor java-9


【解决方案1】:

这两个调用调用同一个构造函数,零参数构造函数:

  1. klass.newInstance()
  2. klass.getDeclaredConstructor().newInstance()

如果构造函数不是公共的,两者都会执行相同的运行时检查来验证调用者的访问权限。唯一的区别是#2 包装了所有已检查的异常,而不是直接抛出。否则它们是相同的,您可以用另一个替换它们。

但这是不同的:

  1. klass.getConstructor().newInstance()

因为它只能返回一个公共构造函数。如果构造函数不是公共的,它会抛出一个NoSuchMethodException

所以你不能把它改成getConstructor(),除非你知道构造函数是公开的。

【讨论】:

  • 谢谢,所以抛出的任何异常都只是有效的初始化失败?
  • @user7294900 是的。
猜你喜欢
  • 1970-01-01
  • 2016-10-02
  • 2012-03-29
  • 1970-01-01
  • 2018-09-13
  • 2011-01-26
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多