2020.10.21(動手動腦)
1.
1 class Grandparent 2 { 3 4 5 public Grandparent() 6 { 7 8 System.out.println("GrandParent Created."); 9 10 } 11 12 13 public Grandparent(String string) 14 { 15 16 System.out.println("GrandParent Created.String:" + string); 17 18} 19 20 } 21 22 23 24 class Parent extends Grandparent 25 { 26 27 28 public Parent() 29 { 30 31 //super("Hello.Grandparent."); 32 33 System.out.println("Parent Created"); 34 35 //super("Hello.Grandparent."); 36 37 } 38 39 } 40 41 42 43 classChild extends Parent 44 { 45 46 47 public Child() 48 { 49 50 System.out.println("Child Created"); 51 52 } 53 54 } 55 56 57 58 public class TestInherits 59 { 60 61 62 public static void main(String args[]) 63 { 64 65 Child c = new Child(); 6667 }
結論:
1、子類的構造方法在執行之前,必須先呼叫父類的構造方法
2、通過 super 呼叫父類構造方法,super必須是子類構造方法中編寫的第一個語句
3、super本身就是呼叫父類的構造方法,而且可以執行父類被隱藏的成員變數和被覆蓋的父類成員方法
思索:為什麼子類的構造方法在執行之前,必須呼叫父類的構造方法?能不能反過來?為什麼不能反過來?
答:不能,子類擁有父類的成員變數和成員方法,如果不呼叫父類的構造方法,則從父類繼承而來的成員變數和成員方法不能進行初始化。而不能反過來呼叫原因是,因為父類不能知道子類有什麼成員變數和成員方法並且這樣做子類不能在父類幫助下完成繼承來的成員變數的初始化,導致成員變數無法初始化,程式就會報錯,無法執行。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.
1 public class ExplorationJDKSource { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 System.out.println(new A()); 8 } 9 10 } 11 12 class A{}
程式中,main方法實際上呼叫的是: public void println(Object x),這一方法內部呼叫了String類的valueOf方法。
valueOf方法的內部又呼叫Object.toString方法
而Object.toString方法的程式碼是:
public String toString(){
return getClass().getName() +"@" + Integer.toHexString(hashCode());
}
hashCode方法是本地方法,是JVM的設計者實現的: public native int hashCode();
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3.
1 class Mammal{} 2 class Dog extends Mammal {} 3 class Cat extends Mammal{} 4 5 public class TestCast 6 { 7 public static void main(String args[]) 8 { 9 Mammal m; 10 Dog d=new Dog(); 11 Cat c=new Cat(); 12 m=d; 13 //d=m; 14 d=(Dog)m; 15 //d=c; 16 c=(Cat)m; 17 18 } 19 }
d=m錯誤:不能從Mammal類轉換到Dog類;
d=c錯誤:不能從Cat類轉換到Dog類;
c=(Cat)m正確:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------、
4.
1 public class ParentChildTest { 2 public static void main(String[] args) { 3 Parent parent=new Parent(); 4 parent.printValue(); 5 Child child=new Child(); 6 child.printValue(); 7 8 parent=child; 9 parent.printValue(); 10 11 parent.myValue++; 12 parent.printValue(); 13 14 ((Child)parent).myValue++; 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 class Child extends Parent{ 27 public int myValue=200; 28 public void printValue() { 29 System.out.println("Child.printValue(),myValue="+myValue); 30 } 31 }
原因:
前兩行正常輸出,父類物件呼叫父類的方法,子類物件呼叫子類的方法;
第三行,當子類與父類擁有一樣的方法,並且讓一個父類變數引用一個子類物件時,到底呼叫哪個方法,由物件自己的“真實”型別所決定;
第四行,當parent=child;僅僅是將parent中有的方法用child的方法代替,所以parent.myValue++;而輸出的是child的printValue(),而printValue()方法中輸出的是child.myValue,所以輸出的是child.myValue;
第五行,強制型別轉換,++作用在child的myValue,所以輸出的也是child的myValue,而不是parent的myValue;
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6.
在子類中,若要呼叫父類中被覆蓋的方法,可以使用super關鍵字。
1 class test{ 2 void play() { 3 System.out.println("我是父類test"); 4 } 5 } 6 7 class test11 extends test{ 8 void play() { 9 super.play(); 10 } 11 } 12 public class test1 13 { 14 public static void main(String[] args) { 15 test11 t=new test11(); 16 t.play(); 17 } 18 19 }