Ami*_*rad 91 java constructor runtime instantiation
瑞安DELUCCHI问这里的评论#3 汤姆Hawtin的回答是:
为什么Class.newInstance()"邪恶"?
这是为了响应代码示例:
// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();
Run Code Online (Sandbox Code Playgroud)
那么,为什么它是邪恶的?
Chr*_*ung 81
Java API文档解释了原因(http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance()):
请注意,此方法传播由Nullary构造函数抛出的任何异常,包括已检查的异常.使用此方法可以有效地绕过编译时异常检查,否则将由编译器执行.该
Constructor.newInstance
方法通过将构造函数抛出的任何异常包装在(checked)中来避免此问题InvocationTargetException
.
换句话说,它可以击败已检查的例外系统.
ale*_*ich 20
还有一个原因:
现代IDE允许您查找类用法 - 如果您和您的IDE知道哪些代码正在使用您计划更改的类,则它在重构期间会有所帮助.
如果不明确使用构造函数,而是使用Class.newInstance(),则可能无法在重构期间找到该用法,并且在编译时此问题不会显现.
我不知道为什么没有人提供一个简单的基于例子的解释,Constructor::newInstance
例如,因为自从java-9 以来最终 Class::newInstance
被弃用.
假设你有这个非常简单的类(无论它是否被破坏):
static class Foo {
public Foo() throws IOException {
throw new IOException();
}
}
Run Code Online (Sandbox Code Playgroud)
并且您尝试通过反射创建它的实例.第一Class::newInstance
:
Class<Foo> clazz = ...
try {
clazz.newInstance();
} catch (InstantiationException e) {
// handle 1
} catch (IllegalAccessException e) {
// handle 2
}
Run Code Online (Sandbox Code Playgroud)
调用它会导致IOException
抛出 - 问题是你的代码没有处理它,既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();
}
Run Code Online (Sandbox Code Playgroud)
将调用句柄3,因此您将处理它.
实际上,Class::newInstance
绕过了异常处理 - 你真的不想要它.