多态是 Java 成为高级语言的特性之一,它可以实现运行时动态绑定,正是因为如此,在使用多态的时候有许多细节的地方需要注意。
1. 多态和字段无关
代码
public class FieldAccess {
public static void main(String[] args) {
Super sup = new Sub();
System.out.println("sup.field = " + sup.field + "sup.getField() = " + sup.getField());
Sub sub = new Sub();
System.out.println("sub.field = " + sub.field + "sub.getField() = " + sub.getField() + "sub.getSuperField() = " + sub.getSuperField());
}
}
class Super {
public int field = 0;
public int getField () {
return field;
}
}
class Sub extends Super {
public int field = 1;
public int getField () {
return field;
}
public int getSuperField () {
return super.field;
}
}
运行结果
sup.field = 0, sup.getField() = 1
sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0
2. 多态和静态方法无关
代码
public class StaticPolymorphism {
public static void main(String[] args) {
StaticSuper sup = new StaticSub();
System.out.println(sup.staticGet());// 调用父类的静态方法,这时候只和类有关
System.out.println(sup.dynamicGet());// 调用子类的方法
}
}
class StaticSuper {
public static String staticGet() {
return "Base staticGet()";
}
public String dynamicGet() {
return "Base dynamicGet()";
}
}
class StaticSub extends StaticSuper {
public static String staticGet() {
return "Derived staticGet()";
}
public String dynamicGet() {
return "Derived dynamicGet()";
}
}
运行结果
Base staticGet()
Derived dynamicGet()
3. 多态时的私有方法
代码
public class PrivateOverride {
private void f () {
System.out.println("private f()");
}
public static void main(String[] args) {
PrivateOverride derived = new Derived();
derived.f();// private f()
}
}
class Derived extends PrivateOverride {
public void f() {
System.out.println("public f()");
}
}
运行结果
private f()
4. 警惕不正当的初始化
问题代码
class Father {
public void show() {
System.out.println("Father.show()");
}
public Father() {
System.out.println("Father before show()");
show();//这里将会调用子类的方法, 此时son中的money没有初始化, 有安全风险
System.out.println("Father after show()");
}
}
class Son extends Father {
private int money = 100;
public Son(int money) {
this.money = money;
System.out.println("Son constructor, money = " + money);
}
@Override
public void show() {
System.out.println("Son.show(), money = " + money);
}
}
public class PolyConstructors {
public static void main(String[] args) {
new Son(88);
}
}
运行结果
Father before show()
Son.show(), money = 0
Father after show()
Son constructor, money = 88
在多态的情况下,这种问题一定要格外小心,最好的方法是在构造的时候不要使用多态。