为什么子类构造函数在初始化父类部分时使用了重写版本的方法?

huangapple go评论102阅读模式
英文:

Why child class constructor when initializing parent's part used overrided version of method?

问题

为什么在使用类B中定义的覆盖方法print()初始化部分类A时要使用```B()```?

预期输出:
A
4

实际输出:
0
4

public class Test
{
    public static void main(String[] args)
    {
        new B();
    }
}

class A
{
    public A()
    {
        print();
    }
    
    public void print()
    {
        System.out.println("A");
    }
}

class B extends A
{
    int a = 4;
    public B()
    {
        print();
    }
    
    @Override
    public void print()
    {
        System.out.println(a);
    }
}
英文:

Why B() when initializing part of class A using overrides method print() defined in class B?

Expected output:
A
4

Real output:
0
4

public class Test
{
    public static void main(String[] args)
    {
        new B();
    }
}

class A
{
    public A()
    {
        print();
    }
    
    public void print()
    {
        System.out.println("A");
    }
}

class B extends A
{
    int a = 4;
    public B()
    {
        print();
    }
    
    @Override
    public void print()
    {
        System.out.println(a);
    }
}

答案1

得分: 0

你已经在类B中重写了print方法。

因此,如果你在类B的实例上调用print,它将始终调用B类中的方法。

这种情况甚至会发生在构造函数仍在运行时,这可能是你没有预料到的,它也可能会引起问题,因为B类中并非所有字段都可能已经初始化。因此,从构造函数中调用任何非final方法是不良实践

你的示例很好地演示了这一点:

你说你预期第一个打印语句的输出是"A",大多数人可能会预期输出是"4",但实际上发生的是输出"0",因为字段B.a尚未初始化。


public A()
{
    print();
}

在这里,print()不是一个静态方法,因此它等同于this.print()。尽管你在类A的构造函数中,但这是作为new B()的一部分从B的构造函数中调用的,所以此时的thisB类的一个实例(在B的构造函数尚未完全完成其工作时)。

英文:

You have overriden print in class B.

So if you call print on an instance of B it will always go there.

This also happens while a constructor is still running, which you seem to not have expected, and it can also cause problem because not all fields in B may have been initialized yet. For this reason, it is bad practice to call any method from a constructor that is not final.

Your example nicely demonstrates that:

You say you expected to output of "A" for that first print statement, most people would have expected the output of "4", but what really happens is you get a "0" because the field B.a is not yet initialized.


public A()
    {
        print();
    }

Here, print() is not a static method, so this is short for this.print(). And even though you are in the constructor of class A, this was being called as part of new B() from the constructor of B, so this is an instance of B (at a point of time when the constructor of B has not yet fully done its work).

huangapple
  • 本文由 发表于 2020年6月29日 06:07:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/62628729.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定