2011-08-29 7 views
8

Java Genericsを使用していない場合、戻り値の型だけが異なる2つのメソッドを同じクラスに持つことはできないと思います。ジェネリックでメソッドオーバーロードを行い、メソッドシグネチャのジェネリック型のみを変更できますか?

言い換えれば、これは違法あろう:例えば以下の2つの方法が存在したかのように異なるインタフェースを実装することができる一般的なタイプを返すメソッドをオーバーロードするとき

public HappyEmotion foo(T emotion) { 
    // do something 
} 

public SadEmotion foo(T emotion) { 
    // do something else 
} 

は同じ本当同じクラス定義:

public <T extends Happy> T foo(T emotion) { 
    // do something 
} 

public <T extends Sad> T foo(T emotion) { 
    // do something else 
} 

これは違法でしょうか?

+2

コンパイルしようとしましたか?コンパイラは合法的で何が違法であるかを速やかにあなたに伝えます。より良い質問は「なぜ...違法ですか?」となります。あなたが理由を理解していない場合。 –

答えて

5

入力パラメータは、あまりにも種類によって異なりので、これは法的な..です。このため

、以下では、

public <T extends Happy> T foo(T emotion) { 
    // do something 
} 

public <T extends Sad> T foo(T emotion) { 
    // do something else 
} 

合法である。しかし、以下ではありません

public <T extends Happy> String foo(T emotion) { 
    // do something 
} 

public <T extends Happy> T foo(T emotion) { 
    // do something else 
} 

ありがとう...

2

これはうまくいきました。

public class Main { 
    public static void main(String[] args){ 
     Main main = new Main(); 
     main.foo("hello"); 
     main.foo(new Integer(5)); 
    } 

    public <T extends String> T foo(T emotion) { 
     return (T) "test"; 
    } 

    public <T extends Integer> T foo(T emotion) { 
     Integer integer = 5; 
     return (T) integer; 
    } 
} 
2

コンパイルされますが、問題が発生するのは、ハッピーまたは悲しいのいずれかが他のスーパークラスである場合です。例えば

、以下のコンパイル:あなたは次のことをコンパイルしようとすると

public <T extends Number> T sayHi() { 
    System.out.println("number"); 
    return null; 
} 

public <T extends Integer> T sayHi() { 
    System.out.println("integer"); 
    return null; 
} 

は、しかし、あなたが問題に実行:

Integer test = sayHi(); 

このケースでは、単純に<Integer>を追加することはできません。なぜならIntegerはまだNumberとIntegerの両方であるからです。以下は幸せなオブジェクトとその逆のインスタンスすることはできません悲しい対象限り、その基本的

Double test2 = <Double>sayHi(); 

をコンパイルしかし

、あなたのコードは、または前に限り、あなたはそれを呼び出すように動作するはずですメソッド名の

+0

同じメソッドシグネチャを持つ2つのメソッドを書くことはできますが、戻り値の型が異なり、コンパイルするとメソッドのオーバーロードの概念に完全に違反します –

1

ジェネリックを使用してJavaでメソッドを区別できます。 JVMはこの型を認識しませんが、引き数または戻り型が異なる場合、Sun/Oracleコンパイラでコンパイルされます。これは、IBM/eclipseコンパイラではコンパイルされません。

これは、バイトコードレベルで起こりたいことを示しています。 http://vanillajava.blogspot.com/2011/02/with-generics-return-type-is-part-of.html

1

これは、他の人が言っているように、合法です。しかし、タイプがお互いを拡張するときに何が起こるかを指摘したいと思います。

のは、我々は二つのインターフェース(単に署名を変更するだけでなく、クラスのために動作します)があるとしましょう:オブジェクトは感情に準拠している場合、JVMが選択されます

<T extends Emotion> void foo(T obj) {} // Referred as foo1 
<T extends Happy> void foo(T obj) {} // Referred as foo2 

interface Emotion {} 
interface Happy extends Emotion {} 

そして、二つの機能をfoo1。 オブジェクトがHappyに準拠する場合、JVMはfoo2ではなくfoo1を選択します。 優先順位に注意してください。それがJVMがあいまいさを解決する方法です。ただし、汎用パラメーターを引数として渡す場合にのみ有効です。

関連する問題