2011-10-14 9 views
11

Javaジェネリックのバグ?

次のクラス階層を作ってみましょう:

public class MyType { 
} 

public class MySuperclass<T extends MyType> { 
    protected Map<String, String> myMap = new TreeMap<String, String>(); 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

public class MySubclass extends MySuperclass { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); // <-- compilation error 
    } 
} 

MySubclassのオーバーライドされたメソッドにコンパイルエラーがあるのはなぜですか? エラーメッセージは「型の不一致:オブジェクトから文字列に変換できません」です。

興味深いのは、 MySubclassの定義で MySuperclassのジェネリッククラスの型を定義すると、コンパイルエラーが消えてしまうことです。

public class MySubclass extends MySuperclass<MyType> { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

誰かがこの動作を説明できますか?私はそれをJavaコンパイラのバグとみなします。

私はjdk1.6.0_24を使用しています。

答えて

12

これはバグではありません。 MySuperclass<MyType>の代わりにMySuperclassを延長すると、生タイプMySuperclassになります。つまり、myMapMap<String, String>ではなくMapとなります。

+1

。それはブロッホの「困惑者」の1人でした。 – Bozho

+0

だからジェネリックは何でもいいですか?生の型を使うと、その型のジェネリックは得られません。 'T 'に全く依存しない部分もありません。 – Thilo

+2

しかし、 'Map ** ** myMap'のジェネリックと共通する' MySuperclass ** ** 'という一般的な定義は何ですか?それらは2つの異なるジェネリック定義で、それらの間には「接続」はありません。理解できません。 –

0

fooはバーのサブタイプ(サブクラスまたはサブインターフェイス)であり、Gは、いくつかの ジェネリック型宣言であれば、それはGあなたは http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf(用を参照することができG.

のサブタイプである場合ではありません詳細)

1

これは本当に不合理です。これは設計上のバグと考えることができます。根本的な原因は、古いものをそのまま維持し、新しいgenerified APIを導入するのではなく、generifiedコレクションAPIを下位互換性を維持するという決定です。この決定は技術的にナンセンスであり、その説明は笑われます。その裏にある本当の理由は、おそらくサンはJava5を押し出すように強制されましたが、十分なリソースがないため、簡単なルート(消去)をとったのです。だからここに私たちは完全に縛られている。このバスタード型システムはそれ自体に問題があるだけでなく、新しい機能を導入する上で大きな障害となります。