1. 程式人生 > >動手動腦(四)

動手動腦(四)

一,

 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 extends
Grandparent { 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值):