根据此: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/