super關鍵字的一些註意事項 子類在執行構造方法時,如果顯式使用super()顯式調用父類構造方法,則該調用必須放代碼塊在第一行 super必須出現在子類的方法或者構造方法中 使用this()顯示調用構造方法,則該調用必須放在代碼塊第一行 由於第一條和第三條限制,super和this不能同時調用構 ...
super關鍵字的一些註意事項
- 子類在執行構造方法時,如果顯式使用super()顯式調用父類構造方法,則該調用必須放代碼塊在第一行
- super必須出現在子類的方法或者構造方法中
- 使用this()顯示調用構造方法,則該調用必須放在代碼塊第一行
- 由於第一條和第三條限制,super和this不能同時調用構造方法
class P1{
public P1(){
//this(); //不可以遞歸調用構造方法
}
public P1(String str){
this();//可以調用重載的構造方法,該調用必須放在第一行
}
}
class S1 extends P1{
public S1(){
super();//顯式調用父類構造方法,該調用必須放在第一行
}
public S1(String str){
this();//無論調用自己的構造方法還是父類的構造方法,都要求在第一行,因此只能調用其中一個
System.out.println("constructor with parameter");
}
}
super 和 this的不同
- 代表的對象不同:
- this:本身調用者這個對象
- super:代表父類對象的引用
- 使用的前提不一樣:
- this沒有發生繼承也可以使用
- super只有在發生繼承時才可以使用,用來表示父類
- 構造方法不一樣:
- this() 調用本類的構造方法
- super() 調用父類的構造方法
方法重寫
方法重寫是多態的一個前提,需要在有繼承關係的前提下,由子類重寫父類的方法,並且存在幾點要求:
- 方法名必須相同
- 參數列表必須相同
- 重寫的方法修飾符範圍可以擴大: public>protected>default>private
- 拋出的異常範圍可以縮小,但不能擴大:ClassNotFoundException(小) ==> Exception(大)
- 返回值類型可以縮小
class P2{
protected S1 run() throws Exception{
System.out.println("Father running!");
return new S1();
}
}
class S2 extends P2{
//修飾符範圍可以擴大,拋出異常範圍可以縮小
//子類方法與父類方法方法名、參數列表必須完全一致
public P1 run() throws ClassNotFoundException{
System.out.println("Son running!");
return new P1();//返回值範圍可以縮小
}
}
多態註意事項
- 多態是方法的多態,屬性沒有多態
- 如果沒有繼承關係的類強制轉換,會導致ClassCastException類型轉換異常
- 多態的存在條件:繼承關係、方法重寫、父類引用指向子類對象, Father f1 = new Son();
因此,有一些方法是不能實現多態的: - static 方法不能實現多態,因為static方法是屬於類的,不屬於實例,當子類定義同名static方法時,會隱藏父類的同名方法。
- final 修飾的類和方法。因為final修飾的類為最終類,不能被繼承,斷子絕孫了,不能滿足繼承關係,自然也就無法實現多態;final修飾的方法不能被重寫,也不能實現多態
- private 修飾的方法。這類方法子類無法訪問,無法產生重寫,因此無法產生多態。
- 在實驗中,筆者註意到父類中 protected 修飾的方法在重寫後,只有在父類包路徑中可以實現多態,當實例範圍超出父類的包之後,該方法即只能被子類實例調用,父類引用指向的子類實例此時不能再調用該方法。
public class Test{
public static void mail(String args[]) throws Exception{
S2 stu = new S2();
stu.run();//無論在哪裡都可以正常調用
P2 per = stu;//父類引用指向子類實例,此時發生多態
per.run();//只有當Test與父類P2在同一個包中時,父類引用per才可以訪問重寫的run()方法。
}
}
instanceof
instanceof的作用是判斷實例的類型
- 當類型由低向高轉化時,如子類型轉化為夫類型,直接使用父類引用指向子類實例即可。
- 當類型由高向低轉化時,需要進行強制類型轉換。這是因為子類實例一定是父類的實例,包含父類的所有域,而父類實例不一定時子類型的實例,包含的域可能更小。
- 子類轉換為父類時,可能丟失自己的方法。
class P3{
}
class S3 extends P3{
static void talk(){
System.out.println("Son talk sth");
}
public class Test{
public static void main(String[] args){
S3 son = new S3();
//此的S3的類方法talk()
son.talk();
P3 per = son;//直接使用父類應用指向子類對象,即完成了類型由低到高的轉換
//轉換成更高等級的父類後,子類中的talk不能被訪問了
//per.talk()//不能訪問
S3 son1 = (S3)per;//由父類型向子類型轉換則需要強制類型轉換
}
}
}
static
static在類載入時的一些作用
public class P4{
{
System.out.println("Anonymous code block!");
}
static {
System.out.println("Static anonymous code block!");
}
public P4(){
System.out.println("No parameter constructor!");
}
public static void main(String[] args){
P4 per1 = new P4();
System.out.println("==============");
P4 per2 = new P4();
}
}
執行結果如下:
可見靜態代碼塊在類載入時首先執行,且在類生命周期中只被執行一次,而匿名代碼塊則在構造方法之前執行,且每次實例化都會執行。