编程语言
首页 > 编程语言> > java – 抽象类:为什么newInstance()没有给出编译错误但构造函数调用给出了错误?

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