根据此:https://docs.oracle.com/javase/tutorial/reflect/member/ctorTrouble.html


  Class.newInstance()引发意外异常
  ConstructorTroubleToo示例显示了Class.newInstance()中无法解决的问题。即,它传播构造函数抛出的任何异常(已检查或未检查)。
  
  这种情况是反射所特有的。通常,不可能编写忽略已检查异常的代码,因为它不会编译。可以使用Constructor.newInstance()而不是Class.newInstance()来包装构造函数抛出的所有异常。


下面,我有一个代码,它没有捕获我注释过的所有未经检查的(RuntimeEcxeption / Error)异常,并且可以编译。那么这种传播在哪里呢?我写的代码忽略了未经检查的异常,这被告知是不可能的。请向我解释有关上述引用的Class.newInstance()有什么问题吗?

try {
        Class<?> c = Class.forName("ConstructorTroubleToo");
        // Method propagetes any exception thrown by the constructor
        // (including checked exceptions).

        Object o = c.newInstance();

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException |
            InstantiationException |
            IllegalAccessException  x
           /*IllegalArgumentException |
             SecurityException x*/ ) {
        x.printStackTrace();
    }

最佳答案

实际上,Class.newInstance()确实传播了它调用的构造函数抛出的任何异常,无论该异常是选中还是未选中。通过调用方法sun.misc.Unsafe.throwException(),可以通过相当隐蔽的方式进行传播。此方法只是引发您提供的异常,它是类sun.misc.Unsafe的一部分,该类包含用于Java中低级“不安全”操作的各种方法。 This article总结了其中一些方法。

在JDK中,有一个src.zip文件,其中包含一些标准Java平台类的源。特别是,您将在此zip文件的java.lang.Class中找到java/lang/Class.java的源。打开此文件,然后查看其中的newInstance()方法。您会发现Class.newInstance()实际上使用Constructor.newInstance()创建对象。

如果构造函数引发异常,则通过Constructor.newInstance()调用构造函数会将'real'异常包装在InvocationTargetException中并引发该异常。但是,未声明Class.newInstance()引发InvocationTargetException,因此它使用Constructor.newInstance()捕获由Unsafe.throwException()引发的InvocationTargetException并引发“真实”异常。

未声明Class.newInstance()引发InvocationTargetException的原因是因为此方法可追溯到Java 1.0。 InvocationTargetException和其他反射API在1.1版中引入了Java。使用Java 1.1编译Java 1.0代码时,将throws InvocationTargetException添加到Class.newInstance()可能会破坏向后兼容性。

关于java - newInstance类传播已检查和未检查的异常-是真的吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30006312/

10-11 05:02