編譯時類型和運行時類型


在學習Java類的繼承時遇到了一點疑惑。於是寫了一點測試代碼。 
先上代碼: 
Class A:

package testone;

public class A { String a = "This is Class A!"; public String getString() { return this.a; } }

Class B:繼承Class A

package testone; public class B extends A { String a = "This is Class B!"; public String getString() { return this.a; } }

測試代碼:

package testone; public class mainTest { public static void main(String[] args) { A a1 = new A(); System.out.println(a1.getClass()+" "+ a1.getString()+" "+a1.a); B b1 = new B(); System.out.println(b1.getClass()+" "+ b1.getString()+" "+b1.a); a1 = b1; System.out.println(a1.getClass()+" "+ a1.getString()+" "+a1.a); b1 = (B)a1; System.out.println(b1.getClass()+" "+ b1.getString()+" "+b1.a); A a2 = new B(); System.out.println(a2.getClass()+" "+ a2.getString()+" "+a2.a); } }

測試結果一:

class testone.A This is Class A! This is Class A! class testone.B This is Class B! This is Class B! class testone.B This is Class B! This is Class A! class testone.B This is Class B! This is Class B! class testone.B This is Class B! This is Class A!

   
  從這個結果可以看出類繼承時,子類會覆蓋與父類相同的屬性。總結一點就是:對象訪問變量看聲明,訪問方法看實際對象類型(new出來的類型)。這在以前的博文(Java中對象的屬性不體現多態性)也提到了。也可以說:屬性無多態,而方法具有多態。 
   
  什么是多態?所謂多態就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時並不確定,而是在程序運行期間才確定,即一個引用變量倒底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。因為在程序運行時才確定具體的類,這樣,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實現上,從而導致該引用調用的具體方法隨之改變,即不修改程序代碼就可以改變程序運行時所綁定的具體代碼,讓程序可以選擇多個運行狀態,這就是多態性。 
   
  而我對通過getClass()方法返回的對象的類類型感到疑惑。注意最后三條賦值語句,為什么賦值之后,輸出結果都顯示它們是Class B的對象?既然都是Class B的對象,為什么只有此時只有對象b1可以訪問Class B的方法? 
  原來getClass()返回的是Object的運行時類。 
  Java中的許多對象(一般都是具有父子類關系的父類對象)在運行時都會出現兩種類型:編譯時類型和運行時類型,例如:Person person = new Student();這行代碼將會生成一個person變量,該變量的編譯時類型是Person,運行時類型是Student。 
  “說明一下編譯時類型和運行時類型:Java的引用變量有兩個類型,一個是編譯時類型,一個是運行時類型,編譯時類型由聲明該變量時使用的類型決定,運行時類型由實際賦給該變量的對象決定。如果編譯時類型和運行時類型不一致,會出現所謂的多態。因為子類其實是一種特殊的父類,因此java允許把一個子類對象直接賦值給一個父類引用變量,無須任何類型轉換,或者被稱為向上轉型,由系統自動完成。引用變量在編譯階段只能調用其編譯時類型所具有的方法,但運行時則執行它運行時類型所具有的方法,因此,編寫Java代碼時,引用變量只能調用聲明該變量所用類里包含的方法(方法表)。與方法不同的是,對象的屬性則不具備多態性。通過引用變量來訪問其包含的實例屬性時,系統總是試圖訪問它編譯時類所定義的屬性,而不是它運行時所定義的屬性“。 
  ”引用變量在編譯階段只能調用其編譯時類型所具有的方法,但運行時則執行它運行時類型所具有的方法,因此,編寫Java代碼時,引用變量只能調用聲明該變量所用類里包含的方法。與方法不同的是,對象的屬性則不具備多態性。通過引用變量來訪問其包含的實例屬性時,系統總是試圖訪問它編譯時類所定義的屬性,而不是它運行時所定義的屬性“。 
  在看一下Java API中關於getClass()方法的講解: 
  這里寫圖片描述 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM