動手動腦4
1.TestInherits.java
public class TestInherits { public static void main(String args[]) { Child c = new Child(); } }
輸出結果:
修改程式碼:
輸出結果:
結論:通過 super 呼叫基類構造方法,必須是子類構造方法中的第一個語句。
2. 為什麼子類的構造方法在執行之前,必須呼叫父類的構造方法?能不能反過來?為什麼不能反過來?
構造方法用於對基類的初始化。當構造一個物件時,先呼叫建構函式對成員函式和成員變數進行初始化,。子類繼承了父類的成員函式和成員變數,若不進行呼叫,則不會對父類的初始化。
3.ExplorationJDKSource.java
public class ExplorationJDKSource { /** * @param args */ public static void main(String[] args) { System.out.println(new A()); } } class A{}
在編譯原始碼時,當遇到沒有父類的類時,編譯器會定義的預設的父類(一般為Object),public void println(Object x),這一方法內部呼叫了String類的valueOf方法。valueOf
public String toString() {
return getClass().getName() +"@" +
Integer.toHexString(hashCode());
}
4.
public class Fruit { public String toString() { return "Fruit toString."; } public static void main(String args[]) { Fruit f=new Fruit(); System.out.println("f="+f); // System.out.println("f="+f.toString()); } }
輸出結果:
結論:在“+”運算中,當任何一個物件與一個String物件,連線時,會隱式地呼叫其toString()方法,預設情況下,此方法返回“類名 @ + hashCode”。為了返回有意義的資訊,子類可以重寫toString()方法。
5. 方法覆蓋
public class parents { public void parents(){ System.out.println("parent!"); } public void parent1(){ System.out.println("parent1!"); } } public class child extends parents { public void child(){ super.parents(); } public void parents(){ System.out.println("child"); } public static void main(String[]args){ child ch=new child(); ch.parents(); ch.child(); ch.parent1(); } }
輸出結果:
6. TestInstanceof.Java
public class TestInstanceof { public static void main(String[] args) { //宣告hello時使用Object類,則hello的編譯型別是Object,Object是所有類的父類 //但hello變數的實際型別是String Object hello = "Hello"; //String是Object類的子類,所以返回true。 System.out.println("字串是否是Object類的例項:" + (hello instanceof Object)); //返回true。 System.out.println("字串是否是String類的例項:" + (hello instanceof String)); //返回false。 System.out.println("字串是否是Math類的例項:" + (hello instanceof Math)); //String實現了Comparable介面,所以返回true。 System.out.println("字串是否是Comparable介面的例項:" + (hello instanceof Comparable)); String a = "Hello"; //String類既不是Math類,也不是Math類的父類,所以下面程式碼編譯無法通過 //System.out.println("字串是否是Math類的例項:" + (a instanceof Math)); } }
輸出結果:
7. 型別轉換
class Mammal{} class Dog extends Mammal {} class Cat extends Mammal{} public class TestCast { public static void main(String args[]) { Mammal m; Dog d=new Dog(); Cat c=new Cat(); m=d; //d=m; d=(Dog)m; //d=c; //c=(Cat)m; } }
結果:d=m; d=c;有錯誤,c=(Cat)m正確
結論:在繼承中,子類可以自動轉換成父類,但父類轉換成子類只有引用型別真正身份才會轉換成功,否則會失敗。
8.
public class ParentChildTest { public static void main(String[] args) { Parent parent=new Parent(); parent.printValue(); Child child=new Child(); child.printValue(); parent=child; parent.printValue(); parent.myValue++; parent.printValue(); ((Child)parent).myValue++; parent.printValue(); } }
結論:由此可得Java的一些語法特性(多型):
當子類與父類擁有一樣的方法,並且讓一個父類變數引用一個子類物件時,到底呼叫哪個方法,由物件自己的“真實”型別所決定,這就是說:物件是子型別的,它就呼叫子型別的方法,是父型別的,它就呼叫父型別的方法。
如果子類與父類有相同的欄位,則子類中的欄位會代替或隱藏父類的欄位,子類方法中訪問的是子類中的欄位(而不是父類中的欄位)。如果子類方法確實想訪問父類中被隱藏的同名欄位,可以用super關鍵字來訪問它。 如果子類被當作父類使用,則通過子類訪問的欄位是父類的。
因此,我們進行程式設計時應避免子類與父類同名的欄位!
9.
public class TestPolymorphism { public static void main(String args[]) { Parent p=new Parent(); p.Introduce(); System.out.println(p.value); p=new Son(); p.Introduce(); System.out.println(p.value); p=new Daughter(); p.Introduce(); System.out.println(p.value); }
多型程式碼:當多個類實現同一介面(或派生自同一抽象類)時,針對這些類所建立的物件呼叫介面所定義的方法時,會分別呼叫相應的類的具體實現程式碼。