/*此總結的主要內容是我在學習JAVA過程中,認爲需要記憶的知識點。並結合之前自己學習C++及javascript的相關知識,註明JAVA在一些情況下與這兩門語言的相同及不同之處。*/
(1)組合
只需將對象引用置於新類中,即意味着組合。
(2)繼承
package reusableClass;
//寫該示例的原因是有次做筆試題,問到同時存在兩個main函數時運行會出現什麼樣的情況
class Cleanser{
private String s="Cleanser";
public void append (String a){
s+=a;
}
public void dilute(){
append(" dilute()");
}
public void apply(){
append(" apply()");
}
public void scrub(){
append(" scrub()");
}
public String toString(){
return s;
}
public static void main(String[] args){
Cleanser x=new Cleanser();
x.dilute();
x.apply();
x.scrub();
System.out.println(x);
}
}
public class Detergent extends Cleanser{
public void scrub(){
append(" Detergent.scrub()");
super.scrub();//調用基類的方法
}
public void foam(){
append(" foam()");
}
public static void main(String[] args){//測試同一個class文件中存在兩個mian方法時的運行情況
Detergent x=new Detergent();
x.dilute();
x.apply();
x.scrub();
x.foam();
System.out.println(x);
System.out.println("Testing base class:");
Cleanser.main(args);
}
//在有兩個main函數時,運行時需要選擇究竟運行哪個類中的函數,無論選擇哪個,都能正常運行。
}
繼承的構建過程是從基類向外擴散的,所以基類在導出類構造器可以訪問它之前,就已經完成了初始化。
不過這種初始化只會調用不帶參數的基類。如果沒有默認的基類構造器,或者想調用一個帶參數的基類構造器,就必須用關鍵字super顯式的編寫調用基類構造器語句,並且配以適當的參數列表。注意,調用基類構造器必須是在導出類構造器中要做的第一件事。
package reusableClass;
//P130
class Game{
Game(int i){
System.out.println("Game constructor");
}
}
class BoardGame extends Game{
BoardGame(int i){
super(i);
System.out.println("BoardGame one constructor");
}
BoardGame(int i,int j){
super(i);
//this(j);//測試用了super調用基類的構造函數後還能否用this調用自身的其它構造函數,結果是不能,
//即在同一個構造函數中,使用了super調用基類的構造函數,就不能再用this調用自身的構造函數
//但是可以考慮在該構造函數中利用this調用其它構造函數,然後用this調用的構造函數調用基類構造函數
//this(i);
System.out.println("BoardGame constructor");
}
}
public class Chess extends BoardGame{
Chess(){
super(11);
System.out.println("Chess constructor");
}
public static void main(String[] args){
//public static void main(String[] args){
Chess x=new Chess();
}
}
PS:在想覆寫基類的某個方法時,可以選擇添加這個註解,防止不想重載時意外的進行了重載。
(3)代理
這是繼承與組合之間的中庸之道。通過實驗成員對象的中一部分方法,即能對成員對象有一定的控制力,又能避免暴露成員對象的所有方法。(4)組合與繼承之間的選擇
(5)protected關鍵字(補充上一章內容)
(6)向上轉型
(7)final關鍵字
(8)初始化及類的加載
package reusableClass;
//P146
/*程序運行過程
* (1)首先會試圖訪問main函數
* (2)訪問main函數時,會開始加載main函數所在的類Beetle
* (3)如果現在加載的類有基類,會繼續加載基類,持續此過程,直到加載到根基類
* (4)從根基類開始沿繼承鏈向上依次初始化類中的static聲明
* (5)必要的類被加載完畢後,纔會開始運行main函數
* (6)創建不帶main函數的其它類過程類同(3)(4),接下來纔可以創建類對象,首先,對象中的所有基本類型會被設爲默認值。然後,構造器纔可以被調用。構造器調用也會沿繼承鏈
* 先不斷上溯直到根基類,再依繼承鏈順序執行構造器的其餘部分
*/
class Insect{
private int i=9;
protected int j;
Insect(){
System.out.println("i="+i+",j="+j);
j=39;
}
private static int x1=printInit("static Insect.x1 initialized");
static int printInit(String s){
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect{
private int k=printInit("beetle.k initialized");
public Beetle(){
System.out.println("k="+k);
System.out.println("j="+j);
}
private static int x2=printInit("static Beetle.x2 initialized");
public static void main(String[] args){
System.out.println("main start run");
Beetle b=new Beetle();
}
}
總結中有一段話,是我學習這一章的最大收穫。