2017-05-10 15 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

2番目の例では、 'foo()'の2番目のバージョンだけが、 'main()'で呼び出しているものに一致する署名を持っています。最初の例では、ボックス化を解除する前にジェネリック関数への 'Integer'呼び出しと一致する優先ルールがなければなりません。 –

+10

この行に新しい汎用タイプのパラメータ 'Program'を定義しています:' private static void foo(Program x){'。その型パラメータは 'Program'という名前のクラスとは何の関係もありません。型パラメータの名前を 'Integer'に変更すると、パラメータ' Program x'はあなたの実際のクラス 'Program'の型を突然持ちます。レッスン:存在する実際のクラスに型パラメータを指定しないでください。 – 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は方法のために使用される一般的なパラメータの名前です。任意の名前を使用できます。重要なことは、メソッドの引数がObjectであることです。そのため、Integer引数でメソッドを呼び出すと、Objectをとるバージョンが使用されます。

2番目のケースでは、汎用パラメータの名前はInteger(これは実行しないでください)ですが、このメソッドの引数はプログラムです。したがって、整数で呼び出すと、有効なObjectまたは整数バージョンが存在しないので、値をunboxします。

method overloadingに関しては、オーバーロードが解決される順序が記載されています。これは、最初のバージョンがintメソッドの代わりにObjectメソッドを使用する理由を説明します。

第2の問題は、一般的なパラメータに具体的な型を指定したことです。混乱します。あなたがそれをしないかどうかは分かりやすい。

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

ここでは、Tがパラメータ化された引数です。 2番目のバージョンでは、

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

は、今ではあなたの引数は、プログラムのオブジェクトだけではなく、任意のオブジェクトであることをを持って、明らかです。

+0

これについて議論しているJLSの関連部分のようなものが見つかると、ボーナスポイント^^ –

+0

タイプパラメータ 'Program'は、彼のメインクラスの名前なので、呼び出さないでください。 typeパラメータの名前を 'Integer'に変更すると、パラメータタイプは実際のクラス' Program'に突然変更されます。 – marstran

関連する問題