除 static、final、private 方法外,所有實例方法均為動態綁定。
final:編譯器可內聯優化,性能微增static:屬於類,不屬於實例,無多態行為private:不可被子類訪問,本質等同 finalclass 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(); }
}
public class Test {
public static void main(String[] args) {
StaticSuper sup = new StaticSub();
System.out.println(sup.staticGet()); // Base staticGet() - 靜態綁定
System.out.println(sup.dynamicGet()); // Derived dynamicGet() - 動態綁定
}
}
構造器本質是隱式 static 方法,不能被 override。子類構造器必須顯式或隱式調用父類構造器。
class Glyph {
void draw() { System.out.println("Glyph.draw()"); }
Glyph() {
System.out.println("Glyph() before draw()");
draw(); // 此處調用的是子類覆蓋的 draw()!
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int r) { radius = r; System.out.println("RoundGlyph ctor, radius=" + radius); }
void draw() { System.out.println("RoundGlyph.draw(), radius=" + radius); }
}
new RoundGlyph(5);
// 輸出:
// Glyph() before draw()
// RoundGlyph.draw(), radius=0 ← 半徑尚未初始化!
// Glyph() after draw()
// RoundGlyph ctor, radius=5
上例中步驟 2 調用 draw() 時,步驟 3 尚未執行,radius 仍為默認值 0。
class Super { public int field = 0; public int getField() { return field; } }
class Sub extends Super { public int field = 1; public int getField() { return field; } }
Super sup = new Sub();
System.out.println(sup.field); // 0 - 編譯期綁定 Super.field
System.out.println(sup.getField()); // 1 - 動態綁定 Sub.getField()
子類實際擁有兩個 field,需用 super.field 顯式訪問父類字段。
子類定義同名 private 方法屬於新方法,非覆蓋。編譯不報錯但運行行為違背預期。建議:子類避免使用與父類 private 方法同名的方法。