JVM是否在内部实例化抽象类的对象?

时间:2015-05-08 13:51:35

标签: java abstract-class object-construction

我有一个抽象类及其具体的子类,当我创建子类的对象时,它会自动调用超级构造函数。 JVM是否在内部创建了抽象类的对象?

public abstract class MyAbstractClass {

    public MyAbstractClass() {
        System.out.println("abstract default constructor");
    }

}
public class ConcreteClass extends MyAbstractClass{

    public static void main(String[] args) {
        new ConcreteClass();
    }

}

然后如何在JVM中没有对象的情况下存在构造函数? (如果是抽象类)

构造函数在创建对象后执行,然后不创建抽象类的对象如何执行默认构造函数? (这在Java Doc中提到)

3 个答案:

答案 0 :(得分:6)

  

你是否真的无法实例化抽象类?

  

JVM是否在内部创建了抽象类的对象?

不,但这是一个常见的误解(这对于它来说不是一种不合理的方式;像JavaScript这样的原型语言就是这样做的。)

JVM创建一个对象,该对象属于您创建的类(在您的情况下为ConcreteClass)。它从超类(MyAbstractClass)和它的子类(ConcreteClass)得到的一个对象的方面,但只有一个对象。

该对象是其所有部分的集合,包括似乎具有相同名称的部分,例如由子类重写的超类的方法。实际上,这些方法具有不同的完全限定名称,并且不会相互冲突,这就是为什么可以调用超类的重写方法的版本。

因此,如果它只是一个对象,为什么你会看到对MyAbstractClass的构造函数的调用?在我们回答之前,我需要提一下Java编译器正在做的一些你在源代码中没有看到的东西:

  1. 它正在为ConcreteClass创建默认构造函数。

  2. 在该构造函数中,它调用MyAbstractClass构造函数。

  3. 为了彻底:在MyAbstractClass构造函数中,它正在添加对超类(Object)构造函数的调用,因为super(...)内没有MyAbstractClass调用1}}构造函数。

  4. 以下是Java编译器为您填写的位添加的代码:

    public abstract class MyAbstractClass {
    
        public MyAbstractClass() {
            super();           // <== The Java compiler adds this call to Object's constructor (#3 in the list above)
            System.out.println("abstract default constructor");
        }
    
    }
    public class ConcreteClass extends MyAbstractClass{
    
        ConcreteClass() {      // <== The Java compiler adds this default constuctor (#1 in the list above)
            super();           // <== Which calls the superclass's (MyAbstractClass's) constructor (#2 in the list above)
        }
    
        public static void main(String[] args) {
            new ConcreteClass();
        }
    
    }
    

    好的,尽管如此,让我们点击评论中非常有用的点TheLostMind构造函数不创建对象,他们初始化他们。 JVM创建对象,然后根据需要针对该对象运行尽可能多的构造函数(它们实际上应该被称为 initializers ),以便为每个超类提供初始化其部分的机会对象。

    所以在那段代码中,会发生什么(你可以在调试器中逐步完成它以完全理解它):

    1. JVM创建一个对象

    2. ConcreteClass构造函数被称为

      1. 构造函数所做的第一件事是调用它的超类的构造函数,在本例中是MyAbstractClass的构造函数。 (请注意,这是绝对要求:Java编译器不允许在超类构造函数调用之前在构造函数本身中使用任何逻辑。)

        1. 构造函数所做的第一件事是调用它的超类的构造函数(Object

        2. Object构造函数返回时,MyAbstractClass构造函数的其余部分运行

      2. MyAbtractClass构造函数返回时,ConcreteClass构造函数的其余部分运行

    3. 该对象作为new ConcreteClass()表达式的结果返回。

    4. 请注意,如果存在具有初始值设定项的实例字段,则上述内容会变得更复杂。有关完整详细信息,请参阅JLS和JVM规范。

答案 1 :(得分:3)

JVM不会创建抽象类的对象。它正在调用它的超级构造函数

答案 2 :(得分:1)

JVM将创建一个对象,一个具体类的实例,它继承抽象类的字段和方法