在本教程中,我們將借助示例學(xué)習(xí)Java中的super關(guān)鍵字。
Java中的super關(guān)鍵字在子類中用于訪問父類成員(屬性,構(gòu)造函數(shù)和方法)。
在學(xué)習(xí)super關(guān)鍵字之前,請確保已經(jīng)了解Java繼承。
調(diào)用子類中重寫的父類的方法。
如果超類(superclass)和子類(subclass)都有同名的屬性,則訪問超類的屬性(字段)。
從子類構(gòu)造函數(shù)顯式地調(diào)用超類無參數(shù)化構(gòu)造函數(shù)或參數(shù)化構(gòu)造函數(shù)。
下面讓我們了解所有這些用途。
如果在超類和子類中都定義了相同名稱的方法,則子類中的方法將覆蓋超類中的方法。這稱為方法重寫。
class Animal { //方法 public void display(){ System.out.println("I am an animal"); } } class Dog extends Animal { //重寫方法 @Override public void display(){ System.out.println("I am a dog"); } public void printMessage(){ display(); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.printMessage(); } }
輸出結(jié)果
I am a dog
在本示例中,通過創(chuàng)建Dog類的對象dog1,我們可以調(diào)用它的方法printMessage(),然后該方法執(zhí)行display()語句。
由于display()在兩個類中都定義,所以子類Dog的方法覆蓋了超類Animal的方法。因此,調(diào)用了子類的display()。
如果必須調(diào)用超類的重寫方法怎么辦?
如果需要調(diào)用超類Animal的重載方法display(),則使用super.display()。
class Animal { //方法 public void display(){ System.out.println("I am an animal"); } } class Dog extends Animal { //重寫方法 @Override public void display(){ System.out.println("I am a dog"); } public void printMessage(){ //這調(diào)用重寫方法 display(); // 這調(diào)用父類的方法 super.display(); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.printMessage(); } }
輸出結(jié)果
I am a dog I am an animal
在這里,上述程序是如何工作的。
超類和子類可以具有相同名稱的屬性。我們使用super關(guān)鍵字來訪問超類的屬性。
class Animal { protected String type="動物"; } class Dog extends Animal { public String type="哺乳動物"; public void printType() { System.out.println("我是 " + type); System.out.println("我是一只 " + super.type); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.printType(); } }
輸出:
我是哺乳動物 我是一只動物
在這個實(shí)例中,我們在超類Animal和子類Dog中定義了相同的實(shí)例字段類型。
然后我們創(chuàng)建了Dog類的對象dog1。然后,使用此對象調(diào)用printType()方法。
在printType()函數(shù)內(nèi)部,
type - 指的是子類Dog的屬性。
super.type - 指超類Animal的屬性。
因此,System.out.println("我是 " + type);輸出 “我是哺乳動物”,并且,System.out.println("我是一只 " + super.type);打印輸出“我是一只動物”。
眾所周知,創(chuàng)建類的對象時,將自動調(diào)用其默認(rèn)構(gòu)造函數(shù)。
要從子類構(gòu)造函數(shù)中顯式調(diào)用超類構(gòu)造函數(shù),我們使用super()。這是super關(guān)鍵字的一種特殊形式。
注意:super() 只能在子類構(gòu)造函數(shù)中使用,并且必須是第一條語句。
class Animal { //Animal類的默認(rèn)或無參數(shù)構(gòu)造函數(shù) Animal() { System.out.println("I am an animal"); } } class Dog extends Animal { // Dog類的默認(rèn)或無參數(shù)構(gòu)造函數(shù) Dog() { //調(diào)用超類的默認(rèn)構(gòu)造函數(shù) super(); System.out.println("I am a dog"); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); } }
輸出結(jié)果
I am an animal I am a dog
在這里,當(dāng)Dog類的對象dog1被創(chuàng)建時,它會自動調(diào)用該類的默認(rèn)或無參數(shù)構(gòu)造函數(shù)。
在子類構(gòu)造函數(shù)中,super()語句調(diào)用超類的構(gòu)造函數(shù)并執(zhí)行其中的語句。因此,我們得到的結(jié)果“I am an animal”。
然后,程序流返回到子類構(gòu)造函數(shù)并執(zhí)行其余語句。 因此,打印輸出“I am a dog”。
但是,不是必須使用super()。 即使在子類構(gòu)造函數(shù)中沒有使用super(),編譯器也會隱式調(diào)用超類的默認(rèn)構(gòu)造函數(shù)。
那么,如果編譯器自動調(diào)用super(),為什么還要顯式它,而使用冗余代碼呢?
如果必須從子類構(gòu)造函數(shù)中調(diào)用超類的參數(shù)化構(gòu)造函數(shù)(帶有參數(shù)的構(gòu)造函數(shù)),則必須顯式地使用它。
帶參數(shù)的super()必須始終是子類的構(gòu)造函數(shù)體中的第一個語句,否則,將出現(xiàn)編譯錯誤。
class Animal { //默認(rèn)或無參數(shù)的構(gòu)造函數(shù) Animal() { System.out.println("I am an animal"); } //參數(shù)化構(gòu)造函數(shù) Animal(String type) { System.out.println("Type: "+type); } } class Dog extends Animal { //默認(rèn)構(gòu)造函數(shù) Dog() { //調(diào)用超類的參數(shù)化構(gòu)造函數(shù) super("Animal"); System.out.println("I am a dog"); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); } }
輸出結(jié)果
Type: Animal I am a dog
編譯器可以自動調(diào)用無參數(shù)構(gòu)造函數(shù)。但是,它不能調(diào)用帶有參數(shù)的構(gòu)造函數(shù)。
如果必須調(diào)用參數(shù)化的構(gòu)造函數(shù),則需要在子類構(gòu)造函數(shù)中顯式定義它,如上面代碼中的語句:
super("Animal");
請注意,在上面的示例中,我們使用了super("Animal"),顯式地調(diào)用參數(shù)化構(gòu)造函數(shù)。在這種情況下,編譯器不會調(diào)用超類的默認(rèn)構(gòu)造函數(shù)。