7

テンプレート クラスに関連しないコレクションがその型を削除するのはなぜですか? 以下に例を示します: (申し訳ありませんが、私が混乱しているエラーのためにコンパイルされません。)

package test;

import java.util.ArrayList;
import java.util.List;

public class TemplateTest {

    public static class A { }

    public static class B<T extends Comparable> {
        List<A> aList = new ArrayList<A>();

        public List<A> getAList() {
            return aList;
        }

        public int compare(T t, T t1) {
            return t.compareTo(t1);
        }
    }

    public static void main(String[] args) {
        B b = new B();
        for (A a : b.getAList()) { //THIS DOES NOT WORK

        }
        List<A> aList = b.getAList(); //THIS WORKS
        for (A a : aList) {

        }
    }
}

このコードは、コンパイル時にエラーをスローします。

test/TemplateTest.java:24: incompatible types
    found   : java.lang.Object
    required: test.TemplateTest.A
        for (A a : b.getAList()) {

Blikeのテンプレートを指定した場合B<String>、または B からテンプレートを完全に削除した場合、すべて問題ありません。

どうしたの?

編集:Bをジェネリックにする必要はないと指摘されたので、Bに追加しました

4

3 に答える 3

8

はい、未加工の型を使用すると、宣言に失敗した型レベルのパラメーターだけでなく、クラスのすべての型パラメーターが失われるという既知の動作です。

問題の一部は次のとおりです。

のように B のテンプレートを指定した場合B<String>、または B からテンプレートを完全に削除した場合、すべて問題ありません。

これはオプションではありません。型パラメーターを指定するかどうかを選択する必要はありません。パラメータを指定せずにコンパイルする唯一の理由は、下位互換性のためです。型パラメーターが欠落している新しいコードを記述することは、プログラミング エラーです。

List<A> list = b.getList()は型を正しく解釈しません。任意のキャストに効果的に固執し、割り当てが正しいことを信頼しているだけです。コンパイラの警告を見ると、実際には安全でない変換の警告が生成されています。

for(A a : b.getList()) {}挿入されたキャストはコンパイラが生成したコード内にあるため、その警告をエラーにアップグレードします。そのため、警告を出すだけでなく、安全でないコードの自動生成をまったく拒否します。

Java言語仕様から:

生の型の使用は、レガシー コードの互換性への譲歩としてのみ許可されています。Java プログラミング言語に汎用性が導入された後に記述されたコードで生の型を使用することは、強くお勧めできません。Java プログラミング言語の将来のバージョンでは、生の型の使用が禁止される可能性があります。

要するに、JavaジェネリックがC++テンプレートと共有する唯一の重要なものは <> 構文です:)

詳細:生の型とは何ですか?なぜそれを使用すべきではないのですか?

于 2013-02-14T19:31:06.357 に答える
1

まず、Javaでは、C ++のようなテンプレートではなく、ジェネリックです。

Tクラスでジェネリック型パラメーターを宣言してBいますが、使用していません。クラス定義全体ではTなく、を使用する必要があります。AB

public static class B<T> {
    List<T> aList = new ArrayList<T>();

    public List<T> getAList() {
        return aList;
    }
}

次に、クラスのインスタンスを宣言するときに型パラメーターを使用する必要がありますB

B<A> b = new B<A>();

ただし、メソッド名が示すように、aList変数が常に型のオブジェクトを保持することがわかっている場合は、クラスをジェネリックにする理由はありません。AgetAListB

于 2013-02-14T18:57:44.050 に答える
1

これは、次のバグに非常によく似ています。

6760983 : 未使用の型パラメータ トリガー エラーが関連のないメソッドにある

ここで報告されているもの:

未使用の一般的な問題の原因

于 2013-02-14T19:06:47.227 に答える