天天看點

java繼承向上轉型和向下轉型和動态綁定

1 概念: 把引用變量轉化為子類類型,則成為向下轉型。如果把引用變量轉化為父類類型,則成為向上轉型。 

Java代碼  

java繼承向上轉型和向下轉型和動态綁定
  1. public class Base {  
  2.     String var = "baseVar";  
  3.     static String staticVar = "staticBaseVar";  
  4.     void method() {  
  5.         System.out.println("Base method");  
  6.     }  
  7.     static void staticMethod() {  
  8.         System.out.println("Base static Method");  
  9.     }  
  10. }  
  11. public class Sub extends Base {  
  12.     String var = "subVar";  
  13.     static String staticVar = "staticSubVar";  
  14.     // 覆寫父類的method()方法  
  15.     void method() {  
  16.         System.out.println("Sub static Method");  
  17.     }  
  18.     String subVar = "var only belonging to Sub";  
  19.     void subMethod() {  
  20.         System.out.println("Method only belonging to Sub");  
  21.     }  
  22.     public static void main(String args[]) {  
  23.         // who 被聲明為Base類型,引用Sub執行個體  
  24.         Base who = new Sub();  
  25.         System.out.println("who.var=" + who.var);// print:who.var=baseVar  
  26.         System.out.println("who.staticVar=" + who.staticVar);// print:who.staticVar=staticBaseVar  
  27.         who.method();// print:Sub static Metho  
  28.         // 這裡為什麼不列印Base method呢 這是java動态機制的表現,  
  29.         // 雖然who的類型是Base 但是 實際引用的是Sub類 new Sub()會在堆區配置設定記憶體空間  
  30.         // 當who.method()方法時,jvm會根據who持有的引用定位到堆區的Sub執行個體  
  31.         // 再根據Sub持有的引用 定位到方法區Sub類的類型資訊 獲得method的位元組  
  32.         // 在目前環境下(上面代碼所示)獲得method的位元組碼,此時Sub類複寫了Base的method的方法,  
  33.         // 獲得method的位元組碼,直接執行method包含的指令,  
  34.         // 如果沒有複寫method方法 則去獲得Base類的位元組碼 執行包含的指令(這個機制實作有待去研究有關資料)  
  35.         who.staticMethod();// print:Base static Method  
  36.         // who.subVar="123";//編譯錯誤  
  37.         // who.subMethod();//編譯錯誤  
  38.         // 對于一個引用變量,java編譯器按照它什麼的類型來處理,這裡who 的類型是Base類型的引用變量.不存在subVar  
  39.         // 和subMethod方法  
  40.         // 如果要通路Sub類成員,可以進行強制類型轉換(向下轉型)  
  41.         Sub sub = (Sub) who;  
  42.         sub.subVar = "23";  
  43.         sub.subMethod();  
  44.         Base base2 = new Base();  
  45.         Sub sub2 = (Sub) base2;  
  46.         sub2.subMethod();  
  47.         // 編譯通過 但是抛出ClassCastException  
  48.         // sub2實際引用的是Base執行個體  
  49.         // 對應一個引用類型的變量,運作時jvm按照它實際引用的對象來處理,假設上面能夠通過,但是  
  50.         // 當我們sub2引用變量調用subMethod()方法時,我們看到在Base類中并沒有subMethod方法。  
  51.         // 由此可見 ,子類對象可以向上轉型為父類對象,但是父類對象不能轉換為子類對象,父類擁有的成員子類  
  52.         // 子類肯定也有,而子類擁有的成員父類不一定有。上面就是一個例子。  
  53.         // 在運作時環境中,通過引用類型變量來通路所引用的方法和屬性時,java虛拟機采用如下綁定機制。  
  54.         // 1 執行個體方法與引用變量 實際引用的對象 的方法綁定 屬于動态綁定.由運作時jvm動态決定的。  
  55.         // 2 靜态方法與引用變了所聲明的對象 的方法綁定 屬于靜态綁定 在編譯階段就已經做了綁定  
  56.         // 3 成員變量 (靜态和執行個體)與引用變量所聲明的類型的成員變量綁定屬于靜态綁定。  
  57.     }  
  58. }  

Java代碼  

java繼承向上轉型和向下轉型和動态綁定
  1. abstract class A {  
  2.     abstract void method();  
  3.     void test() {  
  4.         method();// 這裡調用哪個類的method方法呢  
  5.     }  
  6. }  
  7. public class B extends A {  
  8.     @Override  
  9.     void method() {  
  10.         System.out.println("B method");  
  11.     }  
  12.     public static void main(String[] args) {  
  13.         new B().test(); // print:B method  
  14.         // 方法test()在父類A中定義,它調用了方法method  
  15.         // 但是method在A中是抽象的 但是仍然可以調用  
  16.         // 因為在運作時環境中jvm會執行B的執行個體的method方法  
  17.         // 一個執行個體所屬的類肯定是實作了父類中所有的抽象方法  
  18.     }  
  19. }  

Java代碼  

java繼承向上轉型和向下轉型和動态綁定
  1. class A {  
  2.     void method() {  
  3.         System.out.println("A method");  
  4.     };  
  5.     void test() {  
  6.         method();// 這裡調用哪個類的method方法呢  
  7.     }  
  8. }  
  9. public class B extends A {  
  10.     @Override  
  11.     void method() {  
  12.         System.out.println("B method");  
  13.     }  
  14.     public static void main(String[] args) {  
  15.         //new B().test(); // print:B method  
  16.         // 方法test()在父類A中定義,它調用了方法method  
  17.         // 但是method在A中是抽象的 但是仍然可以調用  
  18.         // 因為在運作時環境中jvm會執行B的執行個體的method方法  
  19.         // 一個執行個體所屬的類肯定是實作了父類中所有的抽象方法  
  20.         new A().test();  
  21.         new B().test();  
  22.         //test()方法在A類中定義,它調用了method()方法,和上面的例子的差別是父類A的method方法  
  23.         //不是抽象的,但是通過new B().test()執行的仍然是子類B的method方法,由此可見  
  24.         //在運作時環境中,當通過B類的執行個體去調用一系列的執行個體方法(包括一個方法調用另外一個方法)  
  25.         //将優先和B類本身包含的執行個體方法動态綁定,如果沒有這個執行個體方法,才會從父類A中繼承來的  
  26.         //執行個體方法動态綁定。   
  27.     }  
  28. }  

——————————————————————————————————————————————————————————————————————————————————————— 實驗測試:

import java.util.ArrayList;
import java.util.List;




public class BreakTest {
	
	public static void main(String arg[]){


		List<String> list = new ArrayList<String>();
		 list.add("a");
		 //編譯時類型是List,運作時類型是ArrayList,而List接口的實作類不隻有ArrayList一個,用一個List類型的引用這是“面向接口程式設計”,好處有很多
		 //,提但是盡量面向接口程式設計,這裡隻說一個這樣寫的好處:
		 //強轉 類型後, list才能調用 ArrayList()實作類的方法
		 ((ArrayList<String>) list).ensureCapacity(16);
		 System.out.println("list size :" + list.size());
		 
		 //Child類向上轉型,編譯時是Father類,可運作時是Child類,調用的方法自然是對子類進行調用。好處,實作面向對象的多态性
		 Father people = new Child();
		 people.eat();
		 
		 Son son =new Son();
		 
	}
	
	//内部内聲明成static
	//因為Father是一個動态的内部類,建立這樣的對象必須有執行個體與之對應,程式是在靜态方法中直接調用動态内部類會報這樣錯誤
	//。  如果類是單獨放在另一檔案裡,不會報錯 
	//這樣的錯誤好比類中的靜态方法不能直接調用動态方法。可以把該内部類聲明為static。或者不要在靜态方法中調用。
	 static class Father{
		public  void eat(){
			System.out.println("father eat!");
		}
	}
	
	static class Child extends Father{
		public  void eat(){
			System.out.println("chlid eat!");
		}
	}
}
           

輸出結果:

java繼承向上轉型和向下轉型和動态綁定

總結: 1 概念: 把引用變量轉化為子類類型,則成為向下轉型。如果把引用變量轉化為父類類型,則成為向上轉型。  2.java繼承向上轉型和向下轉型和動态綁定 顯示的是一個目的:就是java的多态性