Java 类newInstance传播已检查和未检查的异常-是否为真?
据此: Class.newInstance()引发意外异常 ConstructorRoubleToo示例显示Class.newInstance()中存在无法解决的问题。也就是说,它传播构造函数抛出的任何已检查或未检查的异常 这种情况是反思所特有的。通常,不可能编写忽略已检查异常的代码,因为它不会编译。可以使用constructor.newInstance()而不是Class.newInstance()包装构造函数引发的任何异常 下面我有一段代码,它没有捕获任何未检查的(RuntimeEcxeption/Error)异常,我对它们进行了注释并编译了它。那么传播在哪里呢?我编写的代码忽略了未检查的异常,这些异常被告知是不可能的。请解释一下Class.newInstance()在上述引用方面有什么问题Java 类newInstance传播已检查和未检查的异常-是否为真?,java,Java,据此: Class.newInstance()引发意外异常 ConstructorRoubleToo示例显示Class.newInstance()中存在无法解决的问题。也就是说,它传播构造函数抛出的任何已检查或未检查的异常 这种情况是反思所特有的。通常,不可能编写忽略已检查异常的代码,因为它不会编译。可以使用constructor.newInstance()而不是Class.newInstance()包装构造函数引发的任何异常 下面我有一段代码,它没有捕获任何未检查的(RuntimeEcxept
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();
}
试试看{
c类=Class.forName(“构造函数也有问题”);
//方法传播构造函数引发的任何异常
//(包括已检查的例外情况)。
对象o=c.newInstance();
//生产代码应该更优雅地处理这些异常
}catch(ClassNotFoundException |
实例化异常|
IllegalacessException x
/*非法辩论例外|
安全性异常x*/){
x、 printStackTrace();
}
传播意味着异常只会消失,不像包装到InvocationTargetException中一样,反射方法通常会表现出来
实际上,编写忽略选中异常的代码并不是不可能的。从第一个案例考虑:
公共类测试{
//这里没有条款
公共静态void main(字符串[]args){
doThrow(新的SQLException());
}
静态空位点箭头(例外e){
测试doThrow0(e);
}
@抑制警告(“未选中”)
静止的
void doThrow0(异常e)抛出e{
投掷(E)E;
}
}
JVM不区分已检查和未检查的异常,有一些方法可以愚弄Java编译器。Class.newInstance()
确实会传播它调用的、已检查或未检查的构造函数引发的任何异常。通过调用方法sun.misc.Unsafe.throwException()
,以一种相当隐蔽的方式进行传播。这个方法只是抛出您给它的异常,它是类sun.misc.Unsafe
的一部分,该类包含用于Java中低级“不安全”操作的各种方法。总结了其中的一些方法
JDK中有一个src.zip
文件,其中包含一些标准Java平台类的源代码。特别是,您可以在这个zip文件java/lang/Class.java
中找到java.lang.Class
的源代码。打开此文件并查看其中的newInstance()
方法。您会发现Class.newInstance()
实际上使用Constructor.newInstance()
来创建对象
如果构造函数引发异常,则通过constructor.newInstance()
调用构造函数会将“真实”异常包装在InvocationTargetException中并引发该异常。但是,Class.newInstance()
未声明引发InvocationTargetException,因此它会捕获构造函数.newInstance()引发的InvocationTargetException,并使用不安全的.throweException()
引发“真实”异常
Class.newInstance()
没有声明为抛出InvocationTargetException的原因是因为该方法可以追溯到Java 1.0。InvocationTargetException和反射API的其余部分在1.1版中引入Java。添加会将InvocationTargetException
抛出到Class.newInstance()
中,这会破坏使用Java 1.1编译Java 1.0代码时的向后兼容性。这是一个很好的技巧,但参考引文,为什么他们会说该类是“一个无法解决的问题”。newInstance()“传播构造函数抛出的任何异常(已检查或未检查)?这正是其他方法的工作方式,如果它们抛出RuntimeException,我们无法捕获它,如果是checkedException,我们捕获它,这有什么问题?他们希望它如何工作?我想我现在看到了,在某些构造函数中,我抛出了新异常();,通常我不会在没有try+catch的情况下用这样的构造函数编写新类,class.newInstance隐藏了这个异常,我甚至无法捕获它,constructor.newInstance包装到InvocationTargetException中,所以它比class.newInstance更好,因为我可以控制这种情况。是这样还是有其他原因?
public class Test {
// No throws clause here
public static void main(String[] args) {
doThrow(new SQLException());
}
static void doThrow(Exception e) {
Test.<RuntimeException> doThrow0(e);
}
@SuppressWarnings("unchecked")
static <E extends Exception>
void doThrow0(Exception e) throws E {
throw (E) e;
}
}