2013-10-03 30 views
3

我正在學習Java,並且遇到了一些關於重載的問題。以下面的函數作爲例子:Java中的模糊重載

f('a', 'a'); 

如果我們有兩個定義:

static void f(int i, char j){ 
    System.out.println("int_char"); 
} 

static void f(double i, char j){ 
    System.out.println("double_char"); 
} 

這將是確定。因爲所有的第二個參數都完全匹配。但是第一個參數,他們都使用擴大。而且char的擴展順序是:

char -> int -> long -> float -> double 

對於char來實現int,它需要一個步驟。但要實現雙倍,它將需要4個步驟。所以結果是:

int_char 

但我改變paremeter的順序爲:

static void f(int i, char j){ 
    System.out.println("int_char"); 
} 

static void f(char i, double j){ 
    System.out.println("char_double"); 
} 

,編譯器將提出一個錯誤的曖昧。爲什麼?

另一種情況是如下:

static void f(char i, Character j){ 
    System.out.println("char_Character"); 
} 

static void f(Character i, Character j){ 
    System.out.println("Character_Character"); 
} 

兩個第二參數的使用atuoboxing。但是void f(char i,Character j)的第一個參數完全匹配。爲什麼這兩個功能一起會導致模糊?

最後,如果這些功能的人出現與follwing之一:

static void f(Character... i){ 
    System.out.println("Character_varargs"); 
} 

的輸出是不Character_varargs,因爲擴大>拳擊>可變參數。但是當兩個模棱兩可的函數是與Character_varargs類似的:

static void f(char i, Character j){ 
    System.out.println("char_Character"); 
} 

static void f(Character i, Character j){ 
    System.out.println("Character_Character"); 
} 

static void f(Character... i){ 
    System.out.println("Character_varargs"); 
} 

結果將是Character_varargs。爲什麼?

即使我們增加一些非模糊和高優先級的功能於重載功能,如:

static void f(int i, char j){ 
    System.out.println("int_char"); 
} 

static void f(char i, double j){ 
    System.out.println("char_double"); 
} 

static void f(int i, double j){ 
    System.out.println("int_double"); 
} 

static void f(Character... i){ 
    System.out.println("Character_varargs"); 
} 

結果還是Character_varargs。爲什麼?如果只考慮void f(int i,double j)和void f(Character ... i),則輸出應該是int_double。

當編譯器遇到不明確的函數時,是否直接「跳轉」到可變參數函數(如果有)而不考慮其他候選項?

謝謝!

+1

這一切解釋在[JLS](http://docs.oracle.com/javase/specs/jls/se7/html/index.html)中有詳細介紹。你在那裏徹底研究過嗎? –

+0

@JimGarrison對不起。我剛學了兩天就學了Java。我以前真的不知道這些材料。我試圖在那裏找到答案。感謝您的建議。 – Sheng

回答

2

Widen> boxing>可變參數並不完全正確。

適當的是寬>拳擊和拆箱>加寬和拳擊/拆箱和可變參數三個。

在第三步中允許所有三個。

static void f(int i, char j){ 
    System.out.println("int_char"); 
} 

static void f(double i, char j){ 
    System.out.println("double_char"); 
} 

在上述情況下,您可以根據1個特定arg上的加寬距離,按優先順序「排列」它們。但在你下面不能安排他們。

static void f(int i, char j){ 
    System.out.println("int_char"); 
} 

static void f(char i, double j){ 
    System.out.println("char_double"); 
} 

下一個問題是

static void f(char i, Character j){ 
    System.out.println("char_Character"); 
} 

static void f(Character i, Character j){ 
    System.out.println("Character_Character"); 
} 

當需要拳擊被允許用於匹配,(因爲沒有匹配而不拳擊),具有或不具有在第一或第二拳擊所有方法論點被視爲同樣的偏好。所以第一個並不比第二個好,所以我們不能按優先順序排列它們。導致歧義。

現在,如果下面也存在,

static void f(Character... i){ 
    System.out.println("Character_varargs"); 
} 

作爲每個規則,因爲沒有合適的方法被發現是需要用變參裝箱/拆箱所以第3工序後(2曖昧被發現)。最終發現該方法得到解決。


在下面的情況下,我們也需要去第三步,(擴大和裝箱/拆箱和可變參數)找到匹配

static void f(int i, char j){ 
    System.out.println("int_char"); 
} 

static void f(char i, double j){ 
    System.out.println("char_double"); 
} 

static void f(int i, double j){ 
    System.out.println("int_double"); 
} 

static void f(Character... i){ 
    System.out.println("Character_varargs"); 
} 

參考https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12