2

クラスを考えてみましょう:

class OnlyIntegerTypeAllowed<T> {
    OnlyIntegerTypeAllowed(Class<T> clazz) {
        System.out.println(clazz);
        if (clazz != Integer.class)
            throw new RuntimeException();
    }
}

の型引数のみを受け入れるように設計されていIntegerます。if-throwそのコンストラクターにチェックを追加しました。これは、型引数を確認するための非常に一般的な方法です。

ただし、このチェックは次の方法でバイパス (ハッキング、騙され) できます。

OnlyIntegerTypeAllowed<Integer> normalWay =
        new OnlyIntegerTypeAllowed<Integer>(Integer.class);
OnlyIntegerTypeAllowed<String> hacking =
        new OnlyIntegerTypeAllowed<String>((Class<String>) Class.forName(Integer.class.getName()));

上記の2行にはコンパイル エラー例外もスローされていません。

OMG - 型引数を強制するより良い方法はありますか?

4

1 に答える 1

5

タイプ消去へようこそ。実行時に、ソースコードに含まれてClass<T>いたものが - JVM に消去され、などはすべて同じように見えます。これはチェックされていないキャストの意味です-開発者は自分の責任でそれを行います。代わりに、型消去プロセス中にコンパイラによって挿入されたキャストで、後で発生する可能性があります。ジェネリックに型指定された参照が許可されるべきではないオブジェクトを指しているこの状態は、ヒープ汚染として知られています。ClassClass<Integer>Class<String>ClassCastExceptionClassCastException

OMG - 型引数を強制するより良い方法はありますか?

いいえ、これはジェネリック型の安全性に関して Java が提供できる最高のものです。実際にはオプトインです。多くの IDE では、警告の代わりにこれらのコンパイラ エラーを生成することを提案していますが、怠惰なコードや不正なコードは、チェックされていないキャストを自由に実行したり、未加工の型を使用したりできます(これにより、触れたものすべてに暗黙のチェックされていないキャストがもたらされます)。

補足として、チェックされていないキャストが有効な場合もあります。たとえば、Joshua Bloch の効果的な Java 項目 27、「ジェネリック メソッドを優先する」を実装する場合などです。

private static final Comparator<Object> HASH_CODE_COMPARATOR =
        new Comparator<Object>() {
            @Override
            public int compare(final Object o1, final Object o2) {
                return Integer.compare(o1.hashCode(), o2.hashCode());
            }
        };

public static <T> Comparator<T> hashCodeComparator() {
    @SuppressWarnings("unchecked") // this is safe for any T
    final Comparator<T> withNarrowedType =
            (Comparator<T>)(Comparator<?>)HASH_CODE_COMPARATOR;
    return withNarrowedType;
}

ここでは、 が反変的HASH_CODE_COMPARATORに動作するため、チェックされていないキャストは安全です。これはステートレスであり、任意の に対して機能するため、呼び出し元にジェネリック型を決定させることができます。Object

Comparator<String> c = hashCodeComparator();

この場合@SuppressWarnings("unchecked")、未チェックの警告を削除するために使用でき、基本的にコンパイラに信頼するように伝えます。説明のコメントを追加することもお勧めします。

于 2013-09-03T00:32:32.097 に答える