java – 抽象类:为什么newInstance()没有给出编译错误但构造函数调用给出了错误?
作者:互联网
编译器知道AbstractDemo是一个抽象类,而Abstract类无法实例化.
但是当我调用newInstance()方法时,为什么它没有给出编译时错误?
import java.lang.reflect.Constructor;
public abstract class AbstractDemo{
public AbstractDemo(){
System.out.println("Default constructor");
}
public static void main(String args[]){
try{
/* No compilation error for this statement */
AbstractDemo demo = AbstractDemo.class.newInstance();
Constructor[] ctors = AbstractDemo.class.getDeclaredConstructors();
for ( int i=0; i < ctors.length; i++){
System.out.println(ctors[i]);
/* No compilation error for this statement too */
AbstractDemo demo1 = (AbstractDemo) ctors[i].newInstance();
}
/* Compilation error here */
// AbstractDemo demo2 = new AbstractDemo();
}catch(Exception err){
err.printStackTrace();
}
}
}
我运行这个程序时的输出:(我知道错误将会出现,因为我无法为抽象类创建实例.但是为什么在编译时没有给出它让我感到惊讶)
D:\Study\Java>java AbstractDemo
java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at AbstractDemo.main(AbstractDemo.java:10)
编辑:
编译器很聪明地为此语句提供错误:
AbstractDemo demo2 = new AbstractDemo();
但不是这个说法
AbstractDemo demo = AbstractDemo.class.newInstance();
我错过了这里的重要课吗?
解决方法:
编译器的工作是检查编译时规则(呃,编译代码).您调用的方法是Class#newInstance,而不是与AbstractDemo直接相关的任何内容. Class#newInstance将抛出的事实(因为您调用它的Class的实例是抽象类)是运行时关注的问题.
理论上,有时可能在编译时确定对Class的特定实例的特定引用是指抽象类(例如AbstractDemo.class),通常它是不可能的,例如:
void someMethodInMyOwnClass(Class c) {
Object o = c.newInstance();
}
即使它是,那么我们需要某种内置规则或注释系统(例如,编译时信息)说“如果Class实例引用一个抽象类,则不能调用此类的此方法“.
所以我们谈论的是非平凡的工作,并且在完成这项工作时没有实际价值,使其有时成为编译时错误,有时则成为运行时错误.
考虑一下:编译器也可以解决这个问题:
String s = null;
if (s.equalsIgnoreCase("foo")) {
// ...
}
或者永远不会执行此循环的主体:
int x = 10;
while (x < 10) {
System.out.println("Never gets here");
}
但我们没有这样做;那些是运行时问题.
标签:java,instantiation,abstract-class,instanceof 来源: https://codeday.me/bug/20190724/1526096.html