当前位置:  开发笔记 > 编程语言 > 正文

抽象类:为什么newInstance()没有给出编译错误但构造函数调用给出了错误?

如何解决《抽象类:为什么newInstance()没有给出编译错误但构造函数调用给出了错误?》经验,为你挑选了1个好方法。

编译器知道这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();
        }
    }
}

我运行这个程序时的输出:(我知道错误会出现,因为我无法为抽象类创建实例.但是为什么在编译时没有给出它让我感到惊讶)

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(); 

我错过了这里的重要课吗?



1> T.J. Crowder..:

编译器的工作是检查编译时规则(呃,编译代码).你正在调用的方法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");
}

但我们没有这样做; 那些是运行时问题.

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有