2017-05-10 16 views
18
public class Program { 

    private static <Program> void foo(Program x){ 
     System.out.println(x+"-->1"); 
    } 

    private static void foo(final int i){ 
     System.out.println(i+"-->2"); 
    } 

    public static void main(String[] args) { 
     Integer i = 10; 
     foo(i); 
    } 

} 

,輸出是:Java中的泛型如何適用於以下程序?

10-->1 

我沒能找到關於這個主題的相關討論。然而,答案不同的主題弄得我一點: - Return Type of Java Generic Methods

據他們一般<Program>無關,返回類型,但在我而言,如果我改變一點點這個程序如下則輸出是不同的。

public class Program { 

    private static <Integer> void foo(Program x){ 
     System.out.println(x+"-->1"); 
    } 

    private static void foo(final int i){ 
     System.out.println(i+"-->2"); 
    } 

    public static void main(String[] args) { 
     Integer i = 10; 
     foo(i); 
    } 

} 

輸出:

10-->2 

我使用JDK1.7

+0

在你的第二個例子中,只有第二個版本的'foo()'有一個簽名,它可以匹配你在'main()'中調用的內容。在第一個例子中,在拆箱之前必須有一個優先規則匹配對通用函數的「Integer」調用,並調用替代方法。 –

+10

您正在此行上定義一個新的泛型類型參數'Program':'private static void foo(Program x){'。該類型參數與名爲'Program'的類無關。當您將類型參數的名稱更改爲「整數」時,參數「程序x」突然有一種類型的實際類「程序」。課程:不要將您的類型參數命名爲存在的實際類。 – marstran

+2

如果您的泛型參數名稱遵循拼寫爲單個大寫字母的約定,那麼您的代碼將更容易遵循。無論如何,當你將它們命名爲具體類型時,它是毫無希望的混淆,更不用說它是一個範圍。從您的類型名稱中分離您的泛型參數名稱! –

回答

14

在你的第一個例子中,你實際上沒有指定類型爲Program的參數,它是一個泛型。該類型參數與名爲Program的課程無關。您將通過使一個錯字這樣得到相同的結果:

public class Program { 

    private static <Programmmm> void foo(Programmmm x){ 
     System.out.println(x+"-->1"); 
    } 

    private static void foo(final int i){ 
     System.out.println(i+"-->2"); 
    } 

    public static void main(String[] args) { 
     Integer i = 10; 
     foo(i); 
    } 

} 

然而,在第二個例子中,參數是Program類型的字面上,所以當被稱爲foo(10);不匹配,你會得到從第二個結果方法。

13

在第一種情況,是Program用於該方法的一般參數的名稱。它可以是任何名稱。重要的是method參數是一個Object,所以當你用一個Integer參數調用你的方法時,它使用帶Object的版本。

在第二種情況下,通用參數名爲Integer(不要這樣做),但方法所需的參數是程序。所以通過用Integer調用它,不存在有效的Object或整數版本,所以它將該值解開。

根據method overloading,它描述瞭解決超載的順序。這會告訴你爲什麼第一個版本使用Object方法而不是int方法。

第二個問題是你已經命名了你的通用參數具體類型,這是令人困惑的。如果你不這樣做,很容易看出來。

private static <T> void foo(T x){ 
    System.out.println(x+"-->1"); 
} 

現在更清晰了,T是一個參數化參數。在你的第二個版本,

private static <T> void foo(Program x){ 
    System.out.println(x+"-->1"); 
} 

現在很清楚,你的論點是一個程序對象,而不是任何對象。

+0

如果您發現喜歡JLS的相關部分討論此問題的獎勵積分^^ –

+0

不要調用類型參數「程序」,因爲它是他的主類的名稱。當他將類型參數重命名爲「整數」時,參數類型突然變爲實際的類「程序」。 – marstran