2011-08-31 19 views
10

今日、私は面白い何かを見つけました。 次のJava 6クラスを想定:あなたは上記の例をコンパイルしようとした場合タイプ消去を使用したメソッドのオーバーライド

public class Ereasure { 

    public Object get(Object o) { 
     return null; // dummy 
    } 

    public static class Derived<T> extends Ereasure{ 
     // (1) 
     @Override 
     public Object get(T o) { 
       return super.get(o); 
     } 
     // (2) 
     /* 
     @Override 
     public Object get(Object o) { 
       return super.get(o); 
     }*/ 

    } 
} 

、コンパイラは Ereasure.java:9氏は述べています:メソッドは、場合@Override スーパー からメソッドをオーバーライドまたは実装していません。あなたは@Overrideアノテーションを削除します(これは必要ではないはずです)。 Ereasure.java:8:name clash:Ereasure.Derivedのget(T)とEreasureのget(java.lang.Object)は同じ消去を持っていますどちらもどちらももう一方を上書きしない これは少し矛盾しています.TがObjectになるはずなので、親クラスgetメソッドをオーバーライドします。

(1)注釈を付けずにコメントを外す(2)ので、(1)オーバーロードすると(2)どちらも機能しません。 コンパイラ出力:結論として

Ereasure.java:15: get(T) is already defined in Ereasure.Derived 
    public Object get(Object o) { 

、TはObjectにereasedされているが、親がメソッドを取得するオーバーライドすることはできません。

私の質問は今、少なくとも1つの例がコンパイルされていませんか?

+0

@ toto2私はあなたの権利を思っていますが、私はその面白い一見文書化されていないコーナーケースだとも思っています。コンパイラの注意書きによると、Derivedのメソッド定義では、Derivedのgetの無制限型をパブリックObject get(Object o)に変換する必要があります。私は、無限の型から生じるメソッドのディスパッチのあいまいさを解決するために、このことをバイトコードに変換する方法がないと彼は正しいと思います。 – nsfyn55

答えて

2

単純な推測では、コンパイラはオーバーロードを計算する際に一般的なビューを使用しません。もちろん、Tが別のタイプのオブジェクトである場合があるためです。オーバーライドは、特に「get」と呼ばれる複数のメソッドがあり、異なる単一のパラメータ型を持つ場合は、間違っている移動ターゲットTに依存するようになります。そのような場合には、それはちょうど意味をなさないでしょう、そして、推測すると、彼らは物事を単純に保つことを選んだのです。

+0

しかし、一般的に言えば、すべてのジェネリックオブジェクトはすべてのJavaクラスがObjectから派生しているため、オブジェクトです... – user3001

+0

上記のTの下限はObjectですが、他の宣言はしばしば異なる下限を使用します。 –

7

あなたはあなたがやりたいことは不可能である理由を、以下の例で見ることができます:

public class Erasure { 

    public void set(Object o) { 
     return; 
    } 

    // method overloading: (which is valid) 
    public void set(String s) { 
     return; 
    } 

    public static class Derived<S> extends Erasure { 

     // Oops... which one am I supposed to override? 
     // (It would actually be overloading if S was a concrete type 
     // that is neither Object nor String.) 
     @Override 
     public void set(S o) { // does not compile 
     super.set(o); 
     } 
    } 
} 

あなたの問題を解決するには、Erasureがパラメータクラスでなければならないことです。

1

getterとsetterの両方をジェネリックとしてオーバーライドした場合を考えてみましょう。

Derived<String> d = new Derived<String(); 
Erasure e = d; 
e.set(new Object()); 
String s = d.get(); //Class cast exception 

ジェネリックの基本原理は、(a)明示的キャストまたは(b)警告がある場合にのみ、クラスキャスト例外が発生する可能性があることです。あなたが望むことを許可されていれば、上記のいずれも例外なく例外を投げます。

関連する問題