動手動腦(四)
一,
1 public class Grandparent { 2 public Grandparent() 3 { 4 System.out.println("GrandParent Created."); 5 } 6 public Grandparent(String string) 7 { 8 System.out.println("GrandParent Created.String:" + string); 9 } 10 } 11 public class Parent extendsGrandparent { 12 public Parent(){ 13 //super("Hello.Grandparent.");該語句可用於呼叫Grandparent中的有引數的建構函式 14 System.out.println("Parent Created"); 15 //super("Hello.Grandparent.");該語句必須寫在子類構造方法的首句,否則編譯會報錯 16 } 17 } 18 public class Child extends Parent{19 public Child(){ 20 System.out.println("Child Created"); 21 } 22 } 23 public class TestInherits { 24 public static void main(String[] args){ 25 Child c = new Child(); 26 } 27 }
執行結果(呼叫Grandparent預設建構函式):
執行結果(呼叫Grandparent中的有引數的建構函式):
注意:通過super呼叫基類構造方法,必須是子類構造方法的首句!
原因:構造方法的作用為初始化物件,必須先初始化父類,之後才能初始化子類物件。
二,
1 public class ExplorationJDKSource { 2 public static void main(String[] args) { 3 System.out.println(new A()); 4 } 5 6 } 7 class A{}
執行結果:
探究輸出上述結果的原因:
(1)使用javap -c命令反彙編.class檔案
最後我們發現:
main方法實際上呼叫的是:
public void println(Object x),這一方法內部呼叫了String類的valueOf方法。
valueOf方法內部又呼叫Object.toString方法:
public String toString() {
return getClass().getName() +"@" +
Integer.toHexString(hashCode());
}
hashCode方法是本地方法,由JVM設計者實現:
public native int hashCode();
也就是說輸出的是java中頂層基類Object的toString()方法。
三,
1 public class Fruit 2 { 3 public String toString() 4 { 5 return "Fruit toString."; 6 } 7 public static void main(String args[]) 8 { 9 Fruit f=new Fruit(); 10 System.out.println("f="+f); 11 System.out.println("f="+f.toString()); 12 } 13 }
執行結果:
分析:
在“+”運算中,當任何一個物件與一個String物件,連線時,會隱式地呼叫其toString()方法,預設情況下,此方法返回“類名 @ + hashCode”。為了返回有意義的資訊,子類可以重寫toString()方法。
在這個例子中正是Fruit類覆蓋了Object類的toString方法,所以才會輸出“Fruit toString”。
四,
1 public class Parent { 2 public Parent() { 3 System.out.println("Parent Creat"); 4 } 5 public void show() { 6 System.out.println("Parent Wecome"); 7 } 8 } 9 public class Child extends Parent { 10 public Child() { 11 System.out.println("Child Creat"); 12 } 13 public void show() { 14 //super.show();該行是運用關鍵字super呼叫父類中被覆蓋的函式 15 System.out.println("Child Wecome"); 16 } 17 } 18 public class text { 19 public static void main(String[] args) { 20 Child a=new Child(); 21 a.show(); 22 } 23 24 }
執行截圖(未使用super):
執行截圖(使用super):
總結:若要呼叫父類中被覆蓋的方法,可以使用super關鍵字。
五,
1 public class TestInstanceof 2 { 3 public static void main(String[] args) 4 { 5 //宣告hello時使用Object類,則hello的編譯型別是Object,Object是所有類的父類 6 //但hello變數的實際型別是String 7 Object hello = "Hello"; 8 //String是Object類的子類,所以返回true。 9 System.out.println("字串是否是Object類的例項:" + (hello instanceof Object)); 10 //返回true。 11 System.out.println("字串是否是String類的例項:" + (hello instanceof String)); 12 //返回false。 13 System.out.println("字串是否是Math類的例項:" + (hello instanceof Math)); 14 //String實現了Comparable介面,所以返回true。 15 System.out.println("字串是否是Comparable介面的例項:" + (hello instanceof Comparable)); 16 String a = "Hello"; 17 //String類既不是Math類,也不是Math類的父類,所以下面程式碼編譯無法通過 18 //System.out.println("字串是否是Math類的例項:" + (a instanceof Math)); 19 } 20 }
執行截圖:
總結:
判斷一個物件是否可以轉換為指定的型別可以使用運算子instanceof
六,
1 class Mammal{} 2 class Dog extends Mammal {} 3 class Cat extends Mammal{} 4 5 public class TestCast { 6 public static void main(String args[]) 7 { 8 Mammal m; 9 Dog d=new Dog(); 10 Cat c=new Cat(); 11 m=d; 12 //d=m; 編譯無法通過,型別不匹配,不能從Mammal轉換為Dog 13 d=(Dog)m; //將m的型別強制轉換為Dog,與d型別匹配,編譯通過 14 //d=c; 編譯無法通過,型別不匹配,不能從Cat轉換為Dog 15 //c=(Cat)m; 該行會執行時出錯,因為m已經被強制轉換為Dog型別,但Dog型別不能強制轉換為Cat. 16 17 } 18 }
七,
1 public class ParentChildTest { 2 public static void main(String[] args) { 3 Parent parent=new Parent(); 4 parent.printValue();//呼叫父類的printValue()方法,輸出父類的myValue值 5 Child child=new Child(); 6 child.printValue();//呼叫子類的printValue()方法,輸出子類的myValue值 7 8 parent=child;//用子類初始化父類物件 9 parent.printValue();//呼叫Child類的printValue()方法,輸出Child類的myValue值 10 11 parent.myValue++;//使父類的myValue值+1 12 parent.printValue();//因為上面執行了“parent=child;”,所以仍呼叫的是子類的printValue()方法 13 14 ((Child)parent).myValue++;//因為前面使用了強制型別轉換,所以使Child類的myValue值+1 15 parent.printValue();//同上 16 17 } 18 } 19 20 class Parent{ 21 public int myValue=100; 22 public void printValue() { 23 System.out.println("Parent.printValue(),myValue="+myValue); 24 } 25 } 26 27 class Child extends Parent{ 28 public int myValue=200; 29 public void printValue() { 30 System.out.println("Child.printValue(),myValue="+myValue);
//System.out.println("父類中此時myValue值:"+super.myValue); 此行程式碼可用於顯示父類中唄被隱藏的同名欄位 31 } 32 }
執行結果:
總結:
(1)當子類與父類擁有一樣的方法,並且讓一個父類變數引用一個子類物件時,到底呼叫哪個方法,由物件自己的“真實”型別所決定,這就是說:物件是子型別的,它就呼叫子型別的方法,是父型別的,它就呼叫父型別的方法。
(2)如果子類與父類擁有相同的欄位,則子類中的欄位會代替或隱藏父類的欄位,子類方法中訪問的是子類中的欄位(而不是父類中的欄位)。如果子類方法確實想訪問父類中被隱藏的同名欄位,可以用super關鍵字來訪問它。
執行截圖(新增super顯示被隱藏的父類myValue值):