4

このコードがコンパイルされない理由を教えてください。

特定の型 T を提供せずにジェネリック クラスを使用していても、コンパイル時に ArrayList が文字列を保持していることを認識できるはずです。

public class Test {
    public static void main(String[] args){
        Container container = new Container();
        container.strings.add("test");
        String s1 = container.strings.get(0); // does not compile
        ArrayList<String> local = container.strings;
        String s2 = local.get(0); // does compile
    }

    static class Container <T>{
        ArrayList<String> strings = new ArrayList<String>();
    }
}
4

2 に答える 2

7

ジェネリック クラスを生の型 (型を指定しないもの) として使用すると、すべてのジェネリック情報がクラスから削除されます(省略された型が使用されているかどうかに関係なく)。

Container containerしたがって、 ( の代わりにContainer<SomeClass> container)をコーディングすると にArrayList<String> stringsなりArrayList strings、これは であるかのように使用されArrayList<Object>ます。

「修正」するには、タイプを指定しますContainer(タイプを使用しなくても):

Container<Object> container = new Container<Object>();

残りはコンパイルされます。


これが行われる理由は、Java の以前の汎用バージョン (1.4 以前) との下位互換性を維持するためです。

于 2013-01-01T23:34:04.360 に答える
0

ボヘミアンが言ったように、生の型のすべての型引数は破棄されます。最初はバグだと思っていましたが、関連するJLS §4.8を明示的に引用しているバグ データベース (#6244346)にもエントリがあります。

コンストラクター (§8.8)、インスタンス メソッド (§8.4、§9.4)、または非静的フィールド (§8.3) の型 M スーパークラスまたはスーパーインターフェイスから継承されていない生の型 C は、対応する生の型です。 C に対応するジェネリック宣言での型の消去に。

生の型 C の静的メソッドまたは静的フィールドの型は、C に対応するジェネリック宣言の型と同じです。

スーパークラスまたはスーパーインターフェースから継承されていない生の型の非静的型メンバーに型引数を渡すと、コンパイル時エラーになります。

パラメーター化された型の型メンバーを生の型として使用しようとすると、コンパイル時エラーになります。

Stringraw から a を取得できないが、 aに a をList割り当てることができる理由は、後者ではコンパイラーが警告 ( unchecked conversion ) を発行しますが、それを報告しないためです (警告を読みますか?あなたは?:P)。コードを javac と Eclipse コンパイラでテストしましたが、どちらも仕様を尊重しています。ListList<String>

生の型はレガシー コードとの相互運用性のために導入されましたが、この場合、非静的メンバーの型情報を保持することで問題が発生する方法がわかりません。生の型の代わりにパラメータ化された型を使用すると、部分的に移植されたコードを意味するため、この場合の目的は単に後方互換性を確保することではなく、コードが完全な 1.4 であるか、完全に Java 5+ であるかのいずれかで、一貫したコードベースを確保することです。もう 1 つのオプションは、このような生の型を使用すると、同様のコンテキストで無制限のワイルドカードの採用が遅くなる可能性があるということです。

ところで(しかし、あなたは自分でそれを理解したと思います)、型パラメーターを使用しない場合は、単純に無制限のワイルドカードを使用できます。Container<?>

于 2013-01-02T10:44:55.907 に答える