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