2013-02-03 32 views
11

我試圖讓我的頭一輪的Java如何選擇哪個方法被執行:Java的重載方法選擇

//Example 1 prints Square:add(Figure) 
Figure fs = new Square(); 
fs.add(fs); 

//Example 2 prints Square:add(Figure) 
Rectangle rs = new Square(); 
rs.add(fs); 

//Example 3 prints Rectangle:add(Rectangle). Expected Square:add(Square) 
rs.add(new Square()); 

//Example 4 prints Rectangle:add(Rectangle). Expected Square:add(Figure) 
Square ss = new Square(); 
ss.add(rs); 

class Figure 
{ 
    public void add(Figure f){ System.out.println("Figure:add(Figure)"); } 
} 

class Rectangle extends Figure 
{ 
    @Override 
    public void add(Figure f){ System.out.println("Rectangle:add(Figure)"); } 
    public void add(Rectangle r){ System.out.println("Rectangle:add(Rectangle)"); } 
} 

class Square extends Rectangle 
{ 
    @Override 
    public void add(Figure f){ System.out.println("Square:add(Figure)"); } 
    public void add(Square s){ System.out.println("Square:add(Square)"); } 
} 

我所學到here

  • 方法簽名系統會根據確定編譯時間數據類型
  • 調用的實際方法取決於調用該方法的對象的動態類型。

基於此,前兩次調用的結果與預期相同。但是,我不明白例3和4的結果。

它似乎在java language specification中指定,但我不明白。

+1

作爲這個作業問題的作者,我可以確認提供的答案是正確的。 – Dominik

回答

15

不過,我不明白,例如3和4

好結果,讓我們來看看他們的個人。

實施例3

//Example 3 prints Rectangle:add(Rectangle). Expected Square:add(Square) 
rs.add(new Square()); 

的重要的部分是編譯時表達式rsnew Square()類型。

rs只宣佈爲Rectangle,所以編譯器將着眼於通過Rectangle和其超聲明的方法:

public void add(Figure f) 
public void add(Rectangle r) 

類型的表達式new Square()Square的,所以這兩種方法都適用 - 但第二個更具體的

因此,編譯器將調用對rs引用的對象。這就是編譯時的一面。

在執行時,的rs值指的Square一個實例 - 但Square不會覆蓋add(Rectangle)所以挑選的方法是在Rectangle實現:

public void add(Rectangle r){ System.out.println("Rectangle:add(Rectangle)"); } 

實施例4

//Example 4 prints Rectangle:add(Rectangle). Expected Square:add(Figure) 
Square ss = new Square(); 
ss.add(rs); 

再次,讓我們考慮編譯時間類型...... ss是012型和rsRectangle(編譯時類型,請記住)。

通過Square和其超聲明的方法是:

public void add(Figure f) 
public void add(Rectangle r) 
public void add(Square s) 

作爲rs編譯時類型僅Rectangle(未Square),前兩種方法都適用,但第三個是不。因此,在編譯時挑選add(Rectangle)(因爲它比add(Figure)更具體)。

再次,ss執行時間類型爲Square,它不會覆蓋add(Rectangle),所以在Rectangle執行被使用。

讓我知道這裏的任何事情是否令人困惑 - 如果你可以具體說明哪個部分,那會很好。

3
rs.add(new Square()); 

rs的聲明類型是Rectangle。所以它看起來在Rectangle中的一個方法,並且所有的超類採用Square或者與Square兼容的類型作爲參數。最具體的一個是add(Rectangle),因爲Square是一個矩形,並且由於矩形比圖更具體。

Square ss = new Square(); 
ss.add(rs); 

在Square和所有超類中尋找方法add(Rectangle)Rectangle.add(Rectangle)被選中,因爲Square.add(Square)不適用(矩形不是正方形),並且Square.add(Figure)不太具體。