Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java抽象类异常行为_Java_Oop_Inheritance_Abstract Class_Abstract - Fatal编程技术网

Java抽象类异常行为

Java抽象类异常行为,java,oop,inheritance,abstract-class,abstract,Java,Oop,Inheritance,Abstract Class,Abstract,抽象类: public abstract class ParentClass { private static ParentClass mpParentClass; public ParentClass() { mpParentClass = this; } public abstract void method1(); public static ParentClass getInstance() { retu

抽象类:

   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();
    }
}
测试类:

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();
    }
}
在这里,我创建了一个抽象类和一个子类,它扩展了父抽象类

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

在测试类中,若我不创建ChildClass的对象,java将抛出NullPointerException

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


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

您正在创建一个
ChildClass
,然后通过不必要的欺骗调用它的
method1()


你知道
这个
将是
父类
构造函数中的
子类
实例,对吗?它必须是抽象的,因为父类是抽象的,因此不可能有一个
这个
实例来表示它。

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

当您为
子类
调用构造函数时,该方法中的第一个实际调用是对超类构造函数的隐式调用。如果有一个超类构造函数需要/允许替换参数,那么可以手动调用它。但这一切都发生在你身上

当调用超类构造函数时,一个
静态
引用被分配给该新实例,它是一个
子类
实例。(因为在本例中,这就是
这个

如果你要打电话:

new ChildClass();
new ParentClass() {
    public void method1() {
        System.out.println("Anonymous class!");
    }
};
ParentClass.getInstance().method1();
您将看到
“匿名类!”
,因为每次创建
父类实现的任何实例时都会重新分配一个静态引用

关于您的
NullPointerException
-将
mpParentClass
赋值给值的唯一位置是在
ParentClass
的构造函数中。如果从未创建父类的实例,则将永远不会调用此代码,
mpParentClass
将保留其原始值,即
null
。试图在
null
引用上调用方法或访问属性会产生
NullPointerException


要问的问题是:如果您从未实例化任何实现(通过“调用”它们的构造函数),那么如果不是
null
,您希望将
mpParentClass
变量设置为什么?

父类是抽象的,因此您不能直接使用构造函数。静态变量实例默认为null,这将导致NullPointerException。设置此变量的唯一方法是调用构造函数,该构造函数仅在调用子类的构造函数时调用。

这是因为您仅将赋值给
父类
构造函数中的静态字段
mpParentClass
。因此,在创建
ChildClass
的实例之前,
mpParentClass
为空。在您的示例中,当您创建派生类的实例时,会隐式调用基类
ParentClass
构造函数

我可以建议你改用这个吗


ParentClass.getInstance()
是一个静态方法,因此它不需要类的实例来运行

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

因此,如果不执行任何操作,这确实会导致
NullPointerException
,因为您没有调用
父类的构造函数


在您的示例中,首先创建
ChildClass
的一个实例

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

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


因此,在构建之后,
mpParentClass
将包含新创建的
ChildClass

实例,我认为他不会,这就是他为什么要问的原因。@CraigOtis这不是很有帮助。我在第二段给出了答案,很公平。否决票被删除。你的回答(
“不必要的欺骗”
“你确实意识到…”
)有点屈尊俯就,特别是从初学者的角度来看。我不是说屈尊俯就,我的意思是,这完全等同于直接在创建的实例上调用方法,而不是从父类检索引用,然后调用它。