最近差不多把java語言部分學習了一遍,這里把之前書上做標記的內容記錄一下,鞏固基礎。
一、 類和對象
1. java默認值:引用類型數據域為null,數值類型數據域的默認值是0,boolean類型數據域的默認值為false,char類型數據域的默認值為“\u0000”。
其中,java沒有給方法中的局部變量賦默認值。
2. 可見性修飾符:private修飾符只能應用在類的成員上,而public可以用在類或類的成員上。在局部變量上使用修飾符public和private都會導致編譯錯誤。
3.變量作用域:實例變量和靜態變量的作用域是整個類。
4.this語句:java規定了,在構造方法中語句this應在任何其他可執行語句之前出現。
5.包裝類:java中處於對性能的考慮,基本數據類型不作為對象使用。但為了方便,在java.lang包里面提供了各基本數據類型對應的包裝類。
包裝類沒有無參構造方法,可以使用基本數據類型值或表示數值的字符串來構造包裝類。如:new Double(4.2)或new Double("4.2")。
基本類型值與其對應的包裝類間的轉換過程稱為“裝箱”或“拆箱”。
6.String類為:String變量存儲的是對不可變的String對象的引用,String對象里存儲的才是字符串的值。但約定俗成,經常使用術語字符串來表示String變量、String對象和字符串的值。
7. 字符串與數值或字符間的相互轉化:Double.parseDouble("5.44");String.valueOf(5.44)。
8.構造方法鏈:在任何情況下,構造一個類的實例時,將會調用沿着繼承鏈的所有父類的構造方法,這個過程持續到沿着這個繼承層次結構的最后一個構造方法被調用為止。
這里可以用super語句來理解,若子類構造方法中沒有super語句,編譯器會自動在第一行處“添加一行super語句”。
所以,在設計一個會被繼承的類時,最好提供一個無參構造方法,避免出現這種情況:子類Apple沒有顯式定義構造方法,其在實例化時會在調用自己的默認無參構造方法之前調用父類Fruit的無參構造方法,但父類由於定義了有參構造方法,編譯器就不會提供默認的無參構造方法,調用失敗,編譯就會出錯。代碼如下:
1 public class Apple extends Fruit { 2 } 3 4 class Fruit { 5 public Fruit(String name) { 6 System.out.println("Fruit's constrctor is invoked"); 7 } 8 }
此外,super語句不僅可以調用父類的構造方法,也可以調用父類的普通方法。
需要注意的是,只有隱式調用子類構造方法(此處三種情況均可:a.顯示給出有參構造方法,b.顯示給出無參構造方法,c.未給出構造方法,編譯器給出默認無參構造方法)時,
即子類實例化時,才會調用構造方法鏈;顯式調用子類構造方法時(如super語句),就不會調用父類的無參構造方法。
9.方法重寫:存在於繼承中,即子類重寫父類的方法。重寫的方法間必須具有一樣的簽名(函數名和參數列表必須完全相同),但返回類型可以一樣或兼容,
兼容即子類重寫的方法的返回類型時父類被重寫的方法的返回類型的子類型。java語法中提供重寫標注,以避免錯誤。
public class Circle extends GeometricObject { // other methods @override public String toString(){ return super.toString() + "\nradius is " + radius; } }
其中,靜態方法不能被重寫。因為若父類的靜態方法在子類中被重新定義,那么父類的該靜態方法就會被隱藏。但仍然可以使用(父類名.靜態方法名)調用。
10.方法重載:函數名必須完全相同,但參數列表不同。
所有的java類都繼承自Object類,而Object有一個toString()方法。
11.多態:由於子類“大於”父類,若A是B的父類,那么B就包含A,java中就可以用A類型的變量來引用B的對象,此時編譯器就會自動將B中不屬於A的部分忽略。
多態意味着父類型的變量可以引用子類型的對象。即在新建對象實例時,聲明類型時父類型,但實際類型是子類型。
動態綁定:引用變量調用方法時,由其實際類型決定調用哪個具體的方法。JVM會從子類一直往根類(Object類)尋找該方法,一旦找到一個實現,就停止查找,調用即可。
但需要注意的是,雖然具體調用的哪個方法是由變量的實際類型決定,由JVM在運行時動態綁定方法的實現。但,引用變量的聲明類型決定了編譯器編譯時匹配哪個方法。
12.顯式轉換:將父類引用變量顯式轉換成對應子類的引用類型,從而使編譯器明白代碼的意圖。
顯式轉換的目的在於避免編譯錯誤的發生,因為引用變量的聲明類型決定了在編譯階段匹配哪個方法,而父類型有可能並不存在子類型中調用的方法。
此外,對象成員訪問操作符的優先級高於類型轉換操作符的優先級,體現在代碼中如下:
((Circle)object).getArea();
對基本類型值進行顯式類型轉換時,語句會返回一個新的值,而原變量的值不變;但引用變量的顯式轉換則並不會創建一個新的對象:
1 int age =45; 2 byte newAge = (byte)age; // newAge會得到一個新創建的值。 3 4 Object o = new Circle(); 5 Circle c = (Circle)0; // 引用變量o和c指向同一個對象。沒有新建任何對象
13. equals方法和比較操作符==:比較操作符用來比較兩個基礎數據類型的值是否相等或者兩個引用變量的對象地址是否相同,即是否是指向同一個對象。
Object類中equals方法的默認實現為:
1 public boolean equals(Object obj) { 2 return (this == obj); 3 }
然而。equals方法在JAVA API的許多類中都被重寫,用於比較兩個對象的內容是否相等。如java.lang.String和java.util.Date。
由於重寫時應的函數簽名應完全相同,所以重寫的equals方法接收形參須為Object類型,即:
1 @Override 2 public boolean equals(Object o) { 3 if (o instanceof Circle) 4 return radius == ((Circle)o).radius; 5 else 6 return false; 7 }
14. 可見性修飾符
修飾符 | 同一類中 | 同一包中 | 不同包的子類中 | 不同包非子類中 |
public | 1 | 1 | 1 | 1 |
protected | 1 | 1 | 1 | 0 |
默認 | 1 | 1 | 0 | 0 |
private | 1 | 0 | 0 | 0 |
15. 構造方法總結:
構造方法用於構造類的實例,不同於類的屬性和方法,子類不會繼承父類的構造方法,它們只能通過super語句從子類的構造方法中顯式調用。
當然,構造方法也可以調用重載的構造方法或其父類的構造方法,該調用必須在構造方法的第一條語句出現。
若沒有此調用,編譯器會把super()默認左右構造方法的第一條語句,從而調用其父類的無參構造方法。
二、異常處理
1.浮點數除以0是不會產生異常的。
2.異常處理的根本優勢在於將被調用的方法中的檢測錯誤從調用者的處理錯誤中分離出來。
3.java中的異常類分為三種類型:系統錯誤、異常和運行時異常。
系統錯誤是有JVM拋出的,用Error類表示。
異常用Exception類表示,包括ClassNotFoundException類、IoException類等等。
運行時異常用RuntimeException類表示,描述的是代碼的錯誤。如ArithmeticException類、NullPointerException類、IndexOutOfBoundsException類、IllegalArgumentException類等等。
其中運行時異常和系統錯誤及其它們的子類都稱為免檢異常,所有其他的異常都稱為必檢異常。java要求所有必檢異常須在方法頭中聲明並且使用try catch塊處理它們。
因為任何代碼都有可能發生免檢異常,所有java對它們沒有強制要求。
需要注意的是,若在父類的方法中沒有聲明必檢異常,則在其子類中對其重寫時就不能再聲明異常。
4.異常捕獲:由於各種異常類可以從一個共同的父類中派生,則一個catch塊可以捕獲一個父類的異常對象時,它也能捕獲那個父類的所有子類的異常對象。
所以, catch塊的順序十分重要,若父類異常的catch塊在其子類異常的catch塊前面,此時子類的catch塊就形同虛設,就會導致編譯錯誤。
5.鏈式異常:將catch塊中捕獲的異常繼續向上拋出。代碼如下:
1 catch(Exception ex) { 2 throw new Exception("New info from method1", ex) //此處拋出了兩個異常 3 }
6. 自定義異常類時,最好使其成為必檢異常,這樣編譯器就可以強制捕獲這些異常。
7. try-with-resourse語句可以避免錯誤的同時簡化代碼catch塊。
三、抽象類和接口
1.包含抽象方法的類肯定是抽象類,但抽象類可以不全是抽象方法。抽象類的構造方法定義為protected。抽象方法是非靜態的。
即使子類的父類是具體的,這個子類也可以是抽象的。抽象類不能實例化。
2.接口時一種與類相似的結構,只包含常量和抽象方法,以及默認方法和靜態方法。
接口中的所有數據域都是public static final修飾的;接口中的所有方法都是public abstract修飾的。
書寫接口代碼時java允許省略這些修飾符,但在子類實現時方法必須定義為public的。
此外,java8開始,引入了默認接口方法和公有的靜態方法。如:
1 public interface A { 2 // 接口中的默認方法 3 public default void doSomething() { 4 System.out.println("Do something"); 5 } 6 7 // 接口中的公有靜態方法 8 public static int getValue() { 9 return 0; 10 } 11 }
3. Object類中的clone方法自動對所有的數據域進行淺復制。
4.一個類僅能繼承一個父類,但卻可以實現一個或多個接口;一個接口可以繼承一個或多個接口,但不能繼承類。
變量 | 構造方法 | 方法 | |
抽象類 | 無限制 | 構造方法鏈,不能new | 無限制 |
接口 | 所有變量都必須為public static final | 沒有構造方法,不能new | 可以包含public的抽象實例方法、public的默認方法和public的靜態方法 |
三、泛型
四、多線程