Rav*_*abu 3 java abstract-class instantiation instanceof
编译器知道这AbstractDemo是一个抽象类,而抽象类无法实例化.
但是当我调用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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我运行这个程序时的输出:(我知道错误会出现,因为我无法为抽象类创建实例.但是为什么在编译时没有给出它让我感到惊讶)
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)
Run Code Online (Sandbox Code Playgroud)
编辑:
编译器很聪明地为此语句提供错误:
AbstractDemo demo2 = new AbstractDemo();
Run Code Online (Sandbox Code Playgroud)
但不是这个说法
AbstractDemo demo = AbstractDemo.class.newInstance();
Run Code Online (Sandbox Code Playgroud)
我错过了这里的重要课吗?
编译器的工作是检查编译时规则(呃,编译代码).你正在调用的方法Class#newInstance,而不是(直接)与之相关的任何方法AbstractDemo.Class#newInstance将抛出的事实(因为Class您将其称为抽象类的实例)是运行时关注的事实.
理论上,有时可能在编译时确定对特定实例的特定引用是Class指抽象类(例如AbstractDemo.class),通常它是不可能的,例如:
void someMethodInMyOwnClass(Class c) {
Object o = c.newInstance();
}
Run Code Online (Sandbox Code Playgroud)
即使它是,那么我们需要某种内置规则或注释系统(例如,编译时信息)说"如果Class实例引用抽象类,则不能调用此类的此方法. "
所以我们谈论的是非平凡的工作,并且在完成这项工作时没有实际价值,使其有时成为编译时错误,有时则成为运行时错误.
考虑一下:编译器也可以解决这个问题:
String s = null;
if (s.equalsIgnoreCase("foo")) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
或者永远不会执行此循环的主体:
int x = 10;
while (x < 10) {
System.out.println("Never gets here");
}
Run Code Online (Sandbox Code Playgroud)
但我们没有这样做; 那些是运行时问题.
| 归档时间: |
|
| 查看次数: |
1734 次 |
| 最近记录: |