Java抽象类不寻常的行为

抽象类:

   public abstract class ParentClass {
    private static ParentClass mpParentClass;

    public ParentClass() {
        mpParentClass = this;
    }

    public abstract void method1();

    public static ParentClass getInstance() {
        return mpParentClass;
    }
}

儿童班:

public class ChildClass extends ParentClass{
    @Override
    public void method1() {
        System.out.print("ChildClass class method");
    }
}

测试等级:

public class TestClass {
    public static void main(String[] args) {
         ChildClass cl = new ChildClass();
        ParentClass.getInstance().method1();
    }
}

在这里我创建了一个抽象类和一个扩展父抽象类的Child类。

父类抽象类持有对其自身实例的引用,并通过静态方法返回该实例。

在Test类中,如果我不创建ChildClass的对象,则java抛出NullPointerException。

但是在创建ChildClass的对象之后,然后查询ParentClass的实例并调用抽象方法之后,它会调用由ChildClass实现的方法。

我无法理解这种行为。 请任何人解释。


当你第一次实例化一个ChildClass时,你使用parentClass的默认构造函数来实例化具有ChildClass类型的私有字段。 如果你不这样做,私有字段mpParentClass不是实例化的。 所以你有一个NullPointerException


ParentClass.getInstance()是一个静态方法,所以它不需要你的类的一个实例运行。

通过调用此方法,您将返回静态成员mpParentClass 。 但默认情况下,这个成员包含一个null引用。

因此,如果不做任何事情,确实会导致NullPointerException因为您没有调用ParentClass的构造函数。


在你的例子中,你首先创建一个ChildClass的实例。

这将调用该类的默认构造函数。 这个默认构造函数具有调用超类的默认构造函数的标准行为(通过调用super() )。

因此,通过实例化ChildClass您可以调用ParentClass的构造函数,它将mpParentClass项设置为此。 这里指的是你正在创建的ChildClass的实例。

所以在构建之后, mpParentClass将包含新创建的ChildClass实例。


这是发生了什么。

当您为ChildClass调用构造函数时,隐含的是该方法中的第一个实际调用是针对超类构造函数的。 如果您有一个需要/允许备用参数的超类构造函数,则可以手动调用它。 但它发生在你身上。

当调用超类构造函数时,将为该新实例分配一个static引用,该实例是一个ChildClass实例。 (因为这是this是在这种情况下)。

如果您打电话给:

new ChildClass();
new ParentClass() {
    public void method1() {
        System.out.println("Anonymous class!");
    }
};
ParentClass.getInstance().method1();

你会看到"Anonymous class!" ,因为每次创建ParentClass实现的任何实例时都会重新分配一个静态引用。

关于你的NullPointerException - mpParentClass分配给一个值的唯一地方是在ParentClass的构造函数中。 如果您从不创建ParentClass的实例,那么将永远不会调用此代码,并且mpParentClass将保留其原始值(该值为null 。 尝试调用方法或访问null引用上的属性会产生NullPointerException

要问的问题是:如果你从来没有实例化任何实现(通过'调用'它们的构造函数),你期望mpParentClass变量被设置mpParentClass ,如果不是null

链接地址: http://www.djcxy.com/p/96757.html

上一篇: Java Abstract class Unusual behavior

下一篇: Java Decompiler generates abstract enum