程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 向上與向下轉型,向上向下轉型

向上與向下轉型,向上向下轉型

編輯:JAVA綜合教程

向上與向下轉型,向上向下轉型


 向下轉型

  在向下轉型過程中,分為兩種情況:

 1 Father fh=new Father();
 2 if(fh instanceof Son)
 3 {
 4     Son son =(Son)fh;
 5 }

 

 向上轉型

 1 Father fh=new Son();

  

  當需要調用父類的函數時,編譯器如何知道這個父類的引用指向的是哪一個子類的對象呢?這就涉及到動態綁定了

  

  以下引用《JAVA動態綁定的內部實現機制》,作者 飛天金剛 。

  附上鏈接 http://blog.csdn.net/sureyonder/article/details/5569617。

 

  JAVA虛擬機調用一個類方法時,它會基於對象引用的類型(通常在編譯時可知)來選擇所調用的方法。相反,當虛擬機調用一個實例方法時,它會基於對象實際的類型(只能在運行時得知)來選擇所調用的方法,這就是動態綁定,是多態的一種。動態綁定為解決實際的業務問題提供了很大的靈活性,是一種非常優美的機制。

  • Java對象模型

   JAVA虛擬機規范並沒有規定JAVA對象在堆裡是如何表示的。對象的內部表示也影響著整個堆以及垃圾收集器的設計,它由虛擬機的實現者決定。

   JAVA對象中包含的基本數據由它所屬的類及其所有超類聲明的實例變量組成。只要有一個對象引用,虛擬機就必須能夠快速地定位對象實例的數據。另外,它也必須能通過該對象引用訪問相應的類數據(存儲於方法區的類型信息),因此在對象中通常會有一個指向方法區的指針。當程序在運行時需要轉換某個對象引用為另外一種類型時,虛擬機必須要檢查這種轉換是否被允許,被轉換的對象是否的確是被引用的對象或者它的超類型。當程序在執行instanceof操作時,虛擬機也進行了同樣的檢查。所以虛擬機都需要查看被引用的對象的類數據。

   不管虛擬機的實現使用什麼樣的對象表示法,很可能每個對象都有一個方法表因為方法表加快了調用實例方法時的效率。但是JAVA虛擬機規范並未要求必須使用方法表,所以並不是所有實現中都會使用它。

   下面是一種JAVA對象的內存表示:

   

 

   方法數據存放在類的方法區中,包含一個方法的具體實現的字節碼二進制。方法指針直接指向這個方法在內存中的起始位置,通過方法指針就可以找到這個方法。

 

  • 動態綁定內部機制

   方法表是一個指向方法區中的方法指針的數組。方法表中不包含static、private等靜態綁定的方法,僅僅包含那些需要動態綁定的實例方法。

   在方法表中,來自超類的方法出現在來自子類的方法之前,並且排列方法指針的順序和方法在class文件中出現的順序相同,這種排列順序的例外情況是,被子類的方法覆蓋的方法出現在超類中該方法第一次出現的地方。

   例如有超類Base和子類Derive:

  

   1 public class Base 2 { 3 public Base(){} 4 5 public void test() 6 { 7 System.out.println( "int Base" ); 8 } 9 10 public void print(){} 11 } 12 13 public class Derive extends Base 14 { 15 public Derive(){} 16 17 public void test() 18 { 19 System.out.println( "int Derive" ); 20 } 21 22 public void sayHello(){} 23 24 public static void main( String[] args ) 25 { 26 Base base = new Derive(); 27 base.test(); 28 } 29 } View Code

  

   上例中的Base和Derive的方法表如下:

  

   在這個例子裡,test()方法在Base和Derive的方法表中都是同一個位置:索引為1。

   當JAVA虛擬機執行base.test()時,通過base引用可以找到base所指向的實際對象的內存位置,現在虛擬機不知道base引用的實際對象是Base還是Derive。但是根據上面的對象內存模型,虛擬機從對象內存中的第一個指針“特殊結構指針”開始,可以找到實際對象的類型數據和Class實例,這樣虛擬機就可以知道base引用的實際對象是Derive對。為了執行test(),虛擬機需要找到test()的字節碼,方法的字節碼存放在方法區中。虛擬機從對象內存中的第一個指針“特殊結構指針”開始,搜尋方法表的索引1,索引1指向的test()方法是Derive類的test()方法,這就是JAVA虛擬機將要執行的test()的字節碼。現在,虛擬機知道了調用的實際對象是Derive對象,調用的實際test()方法是Derive類的test()方法,所以JAVA虛擬機能夠正確執行-調用base引用的實際對象的方法而不是base引用本身的方法。

   這是動態綁定的一種實現方式,根據不同的JAVA虛擬機平台和不同的實際約束,動態綁定可以有不同的內部實現機制。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved