构造函数中的多态方法(Java)

luk*_*uku 11 java polymorphism inheritance constructor overriding

类在构造函数中A调用public方法f().B类f()使用自己的实现覆盖方法.

假设你intantiate对象B..方法f()对象B将在对象的构造函数被调用A,虽然对象B未完全初始化.

谁能解释这种行为?

编辑:是的,它不推荐练习..但我不明白为什么 Java不调用f()基类的实现A而不是"伸出"到f()派生类的实现B.

码:

class A {
    A() {
        System.out.println("A: constructor");
        f();
    }

    public void f() {
        System.out.println("A: f()");
    }
}

class B extends A {
    int x = 10;
    B() {
        System.out.println("B: constructor");
    }

    @Override
    public void f() {
        System.out.println("B: f()");
        this.x++;
        System.out.println("B: x = " + x);

    }
}

public class PolyMethodConst {
    public static void main(String[] args) {
        new B();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

A: constructor
B: f()
B: x = 1
B: constructor
Run Code Online (Sandbox Code Playgroud)

Bil*_*ill 8

你是对的,这就是它的工作方式.但是不建议这样做,因为从你的班级继承的人可能会无意中破坏它.

  • 作为一般规则,从构造函数调用的任何方法都应该是final或private.Swing特别糟糕.继承Swing类并尝试覆盖setFont是一个冒险. (3认同)

Ara*_*ram 5

每当您创建子类的实例时,首先调用超类构造函数(隐式super())。所以它打印

a: constructor
Run Code Online (Sandbox Code Playgroud)

f()接下来调用,并且由于子类覆盖超类方法,因此f()调用子类。所以你会看到

B: f()
Run Code Online (Sandbox Code Playgroud)

现在,子类还没有初始化(仍然 super() 正在执行)所以x默认值为该值,0因为这是 type 的默认值int。因为你增加了它 ( this.x++;) 它变成1

B: x = 1
Run Code Online (Sandbox Code Playgroud)

现在,超类构造函数完成并在子类构造函数处恢复,因此

B: constructor
Run Code Online (Sandbox Code Playgroud)

实例变量现在设置为您指定的值(针对与类型相对应的默认值(0对于数字、false对于booleannull对于引用))

注意:如果您现在x在新创建的对象上打印 的值,它将是10

由于这是一种不好的做法,如果您尝试这样做,静态代码分析工具(PMD、FIndBugs 等)会警告您。