參考資料:
- 面向對象基礎 - 廖雪峰的官方網站 (liaoxuefeng.com)
方法
Java 的方法允許定義可變參數:
class Group {private String[] names;public void setNames(String... names) {this.names = names;}
}
用可變參數代替數組類型的好處有:
-
可變參數的傳參形式更簡單:
Group g = new Group(); g.setNames("Xiao Ming", "Xiao Hong", "Xiao jun"); // 可變參數 g.setNames(new String[] {"Xiao Ming", "Xiao Hong", "Xiao jun"}); // 數組參數
-
可變參數可以避免傳入
null
基本類型值傳遞,引用類型引用傳遞。
構造方法
class Person {private String name = "Unamed";private int age = 10;public Person(String name, int age) {this.name = name;this.age = age;}
}
在Java中,創建對象實例的時候,先初始化字段,例如,int age = 10;
表示字段初始化為 10
,然后執行構造方法的代碼進行初始化。
方法重載
和 C++ 類似
繼承
使用 extends
關鍵字實現繼承:
class Person {private String name;private int age;public String getName() {...}public void setName(String name) {...}public int getAge() {...}public void setAge(int age) {...}
}class Student extends Person {// 不要重復name和age字段/方法,// 只需要定義新增score字段/方法:private int score;public int getScore() { … }public void setScore(int score) { … }
}
在Java中,沒有明確寫 extends
的類,編譯器會自動加上 extends Object
,所以除了 object
類,任何類都會繼承自某個類。
Java只允許一個class繼承自一個類,因此,一個類有且僅有一個父類。
super
super
關鍵字表示父類:
class Person {protected String name;protected int age;public Person(String name, int age) {this.name = name;this.age = age;}
}class Student extends Person {protected int score;public Student(String name, int age, int score) {this.score = score;}
}
上述代碼會編譯報錯,這是因為在 Java 中,任何 class
的構造方法,第一行語句必須是調用父類的構造方法。如果沒有明確地調用父類的構造方法,編譯器會幫我們自動加一句 super();
由于 Person
類沒有無參的構造方法,所以編譯失敗。
我們可以使用 super
顯示調用父類的構造方法:
class Student extends Person {protected int score;public Student(String name, int age, int score) {super(name, age); // 調用父類的構造方法Person(String, int)this.score = score;}
}
阻止繼承
使用 final
關鍵字修飾不能被繼承的類。
從 Java 15 開始,可以使用 sealed
和 permits
來明確指定能夠繼承該 class
的類:
public sealed class Shape permits Rect, Circle, Triangle {...
}
向上轉型
可以讓父類型的引用變量指向子類型的實例。
向下轉型
Person p1 = new Student(); // upcasting, ok
Person p2 = new Person();
Student s1 = (Student) p1; // ok
Student s2 = (Student) p2; // runtime error! ClassCastException!
向下轉型能否成功由變量實際所指的類型決定,可以使用 instanceof
加以判斷:
Person p = new Person();
System.out.println(p instanceof Person); // true
System.out.println(p instanceof Student); // falseStudent s = new Student();
System.out.println(s instanceof Person); // true
System.out.println(s instanceof Student); // trueStudent n = null;
System.out.println(n instanceof Student); // false
instanceof
實際上判斷一個變量所指向的實例是否是指定類型,或者這個類型的子類。如果一個引用變量為 null
,那么對任何 instanceof
的判斷都為 false
。
從 Java 14 開始,判斷 instanceof
后可以直接轉型為指定變量:
Object obj = "hello";
if (obj instanceof String) {String s = (String) obj;System.out.println(s.toUpperCase());
}// 可以簡寫為Object obj = "hello";
if (obj instanceof String s) {System.out.println(s.toUpperCase());
}
區分繼承和組合
繼承是 is 關系,組合是 has 關系。
多態
可以使用 @Override
讓編譯器幫助檢查是否進行了正確的覆寫:
class Person {public void run() {}
}public class Student extends Person {@Override // Compile error!public void run(String s) {}
}
實例方法調用是基于運行時的實際類型的動態調用,而非變量的聲明類型。
覆寫Object
方法
Object
定義了幾個重要的方法:
toString()
:把 instance 輸出為String
;equals()
:判斷兩個 instance 是否邏輯相等;hashCode()
:計算一個 instance 的哈希值。
final
如果一個父類不允許子類對它的某個方法進行覆寫,可以把該方法標記為 final
。