1. 程式人生 > >轉發一道java基礎題(多型)

轉發一道java基礎題(多型)

這是在網上只看到的一道java關於多型繼承的問題,看著很簡單,結構出乎意料,也是研究了一天終於搞明白了一點


問題來自:http://blog.itpub.net/28562677/viewspace-1200194/


[java]  view plain  copy
  1. public class DispatchTest {  
  2.     public static void
     main(String[] args) {  
  3.         Base b = new Sub();  
  4.         System.out.println(b.x);  
  5.     }  
  6. }  
  7.   
  8. class Base {  
  9.   
  10.     int x = 10;  
  11.   
  12.     public Base() {  
  13.         this.printMessage();  
  14.         x = 20
    ;  
  15.     }  
  16.   
  17.     public void printMessage() {  
  18.         System.out.println("Base.x = " + x);  
  19.     }  
  20. }  
  21.   
  22. class Sub extends Base {  
  23.   
  24.     int x = 30;  
  25.   
  26.     public Sub() {  
  27.         this.printMessage();  
  28.         x = 40;  
  29.     }  
  30.   
  31.     public void printMessage() {  
  32.         System.out.println("Sub.x=" + x);  
  33.     }  
  34. }  


輸出結果為:

Sub.x=0
Sub.x=30
20

對於後兩個很容易理解,對於第一個 Sub.x=0

首先,

[java]  view plain  copy
  1. Base b = new Sub();直接找到子類的構造器,由於子類構造器沒有顯示的使用superthis,所以隱藏super(),呼叫父類無參構造器  
[java]  view plain  copy
  1. 構造器構造器先呼叫superthis,直到呼叫到Object類,  
[java]  view plain  copy
  1. </pre><pre name="code" class="java">然後父類開始例項化物件,執行 int x  = 10;  
[java]  view plain  copy
  1. </pre><pre name="code" class="java">然後父類執行構造器中第一句:  
[java]  view plain  copy
  1. <pre name="code" class="java">this.printMessage();  
[java]  view plain  copy
  1. </pre><pre name="code" class="java">this在java裡只得是當前物件,即執行時的物件,<span style="color:red;">this</span><span style="color:red;">表示某個類的例項,執行時的某個類的例項。(可以用this.getClass.getName()試一下,取到的是子類物件)</span>  

 

所以呼叫的是子類中重寫的printMessge()法,由於子類構造器還沒來的及例項化物件,

輸出:Sub.x=0

所以子類類的 x 為 0 


父類構造器呼叫完成後,然後開始例項化子類物件,執行int x = 30;


子類繼承父類,會重寫父類的屬性和方法

往下執行Sub.x=30被列印


多型中,也可以叫父類引用指向子類物件,

子類重寫完父類後,方法呼叫的是子類的方法,屬性呼叫的是父類的屬性



另附一個列子說明第三個值:

(轉):

java多型中,父類不能引用子類的屬性

class Person{
 String name = "person";
}
 
class Son extends Person {
 String name = "son";
}

public class Test {
 public static void main(String[] args){ 
  Person p = new Son();
  System.out.println(p.name);
 } 
}
結果為person。
為什麼不是son?
變數是靜態繫結,方法是動態繫結。靜態繫結就是變數本身什麼型別,就用哪個裡面的。例如,你的p.name的p是Person型別,那麼name就是Person類中的name。而如果是動態繫結,那麼會從本身型別開始向超型別查詢。如果name是方法,那麼用於p是Son
類的一個物件,所以會從Son開始找name方法,如果找不到再到父類中找。

這下也就很容易理解 b.x=20