基础构造函数的Java调用基方法
如何从Super :: Super()调用Super :: printThree?
在下面的例子中,我改为调用Test :: printThree。
class Super { Super() { printThree(); // I want Super::printThree here! } void printThree() { System.out.println("three"); } } class Test extends Super { int three = 3 public static void main(String[] args) { Test t = new Test(); t.printThree(); } void printThree() { System.out.println(three); } } output: 0 //Test::printThree from Super::Super() 3 //Test::printThree from t.printThree()
你不能 – 这是一个在子类中被覆盖的方法; 你不能强制非虚方法调用。 如果要非虚拟地调用方法,请将方法设为私有或最终方法。
一般来说,在构造函数中调用非final方法是一个坏主意,正是因为这个原因 – 子类构造函数体还没有被执行,所以你有效地在一个尚未完全调用的环境中调用一个方法初始化。
你在这里违反了动态调度和inheritance背后的整个想法。 只是不要这样做(而且无论如何都很难绕过java)。 而是将函数设置为private和/或final,以便不能在inheritance的类中覆盖它
如果Super
需要确保不覆盖printThree()
则需要将该方法声明为final
。 或者, Test
的重写方法可以决定调用overriden方法,如果它选择:
@Override void printThree() { super.printThree(); }
如果基类没有将方法标记为final
,那么它放弃了不让派生类覆盖它并按照自己的意愿行事的权利。