为什么是类。newInstance()"恶魔"?
-
10-07-2019 - |
题
Ryan Delucchi 要求 在这里, 在评论#3 汤姆Hawtin's的回答:
为什么是类。newInstance()"恶魔"?
这个响应的代码样本:
// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();
所以,为什么是恶魔吗?
解决方案
Java API文件解释了为什么(http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance()):
注意,这种方法传播的任何异常引发的nullary构造,包括经过检查的例外。使用这种方法有效地绕过的编写时间异常检查,否则将进行的编译器。的
Constructor.newInstance
方法避免了这个问题通过包装的任何异常引发通过该构造中(检查)InvocationTargetException
.
换句话说,它可以打败的检查的例外情况的系统。
其他提示
一个原因:
现代的IDE让你找到类用途 - 它重构过程中有所帮助,如果您和您的IDE知道您计划什么是使用类代码更改
当你不这样做的构造函数的明确的使用,但使用Class.newInstance()来代替,你可能不会发现重构过程中使用,当你编译这个问题不会显现出来。
我不知道为什么没有人提供了一个简单的例子,基于解释这一点,相比Constructor::newInstance
例如,由于最后的Class::newInstance
是由于Java-9。弃用p>
假设你有一个非常简单的类(不要紧,它坏了):
static class Foo {
public Foo() throws IOException {
throw new IOException();
}
}
和您尝试通过反射来创建它的一个实例。第一IOException
:
Class<Foo> clazz = ...
try {
clazz.newInstance();
} catch (InstantiationException e) {
// handle 1
} catch (IllegalAccessException e) {
// handle 2
}
调用,这将导致handle 1
被抛出 - 问题是,你的代码不处理它,既不handle 2
也不Constructor
会抓住它。
在经由相反做,当它一<=>:
Constructor<Foo> constructor = null;
try {
constructor = clazz.getConstructor();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
Foo foo = constructor.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
System.out.println("handle 3 called");
e.printStackTrace();
}
这手柄3将被调用,因而你将处理它。
实际上,<=>绕过异常处理 - 你真的不想
。