java调用自身构造函数,Java - 子类调用supers构造函数,它调用子类方法而不是自己的...

I'll start with a code example:

class A {

public A() {

f(); //When accessed through super() call this does not call A.f() as I had expected.

}

public void f() {} //I expect this to be called from the constructor.

}

class B extends A {

private Object o;

public B() {

super();

o = new Object(); //Note, created after super() call.

}

@Override

public void f() {

//Anything that access o.

o.hashCode(); //Throws NullPointerException.

super.f();

}

}

public class Init {

public static void main(String[] args) {

B b = new B();

}

}

This program throws a NullPointerException. When the object b enters the constructor of its superclass A and makes a call to the method f() which is overridden by the class B B.f() is called, instead of A.f() which I would have expected.

I thought a superclass wasn't supposed to know if it was subclassed or not but surely this can be used by a class to tell if it's been subclassed or not? What's the reason behind this? Is there any workaround if I really want A.f() to be called instead of B.f()?

Thanks in advance.

Follow up question:

Thanks for the answers. I now understand why it is like it is, but here's a follow up question. Perhaps I'm mistaken but a principle of subtyping is that the supertype should not know that it's been subtyped. This "mechanism" lets a class know if it's been subclassed or not. Consider this code example:

class A {

private boolean isSubclassed = true;

public A() {

f(); //A.f() unsets the isSubclassed flag, B.f() does not.

if(this.isSubclassed) {

System.out.println("I'm subclassed.");

} else {

System.out.println("I'm not subclassed.");

}

}

public void f() {

this.isSubclassed = false;

}

}

class B extends A {

public B() {

super();

}

@Override

public void f() {}

}

public class Init {

public static void main(String[] args) {

new B(); //Subclass.

new A();

}

}

The output of this program is:

I'm subclassed.

I'm not subclassed.

Here A knows it's been subclassed. It's unkown by whom but that doesn't matter. How is this explained? Am I misinformed?

解决方案

The NullPointerException occurs because when you construct an instance of B, the parent constructor (in A) is invoked. This constructor calls the f() method but since the actual type of the object is B, the overridden f() method in B is invoked.

@Override

public void f() {

//Anything that access o.

o.hashCode(); //Throws NullPointerException as o has not been initialised yet

super.f();

}

The lesson here is never to call a method in a constructor which can be overridden by a subclass.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值