5

次のコードがあるとします。

@SuppressWarnings("unchecked")
public static  <T> T implicitCaster(Class<T> cls, Object o) {
    return (T) o;
}

public static <T> T reflectionCaster(Class<T> cls, Object o) {
    return cls.cast(o);
}

コードは、プリミティブに見られる次の例外を除いて、両方のケースで期待どおりに機能します。

public static void main(String[] args) {
    System.out.println(implicitCaster(int.class, 42));
    System.out.println(reflectionCaster(int.class, 42));
}

最初の呼び出しは期待どおりに機能しますが、2 番目の呼び出しはスローしjava.lang.ClassCastExceptionます。

これは、オートボクシングが無視された特殊なケースですか? または、この場合、リフレクション キャストのオートボクシングを提供することは不可能ですか? それとも、この矛盾を引き起こしている何か他のものがありますか?

編集:このコードを呼び出すと、期待どおりに機能します:

public static void main(String[] args) {
    System.out.println(implicitCaster(Integer.class, 42));
    System.out.println(reflectionCaster(Integer.class, 42));
}
4

1 に答える 1

3

これは、型の消去が原因で発生します。

実行時には、ジェネリック型パラメーターは存在しません。
オブジェクトをジェネリック型パラメーターにキャストしても効果はありません。(これが、チェックされていないキャストの警告が表示される理由です)

したがって、最初の行のオートボックスはメソッド42Object渡されます。
次に、関数はそれを返しObject、それが に渡されSystem.out.printlnます。


2 番目の呼び出しは、プリミティブ型のcastメソッドを呼び出します。 オブジェクトはプリミティブ型にキャストできないため、例外がスローされます。(自動ボクシングは純粋にコンパイル時の機能であるため、役に立ちません)int

エラーは、キャストが有効であることを確認するためにcast() チェックするときに発生します。isInstance()

isInstance()言うためのドキュメント:

具体的には、この Class オブジェクトが宣言されたクラスを表している場合、指定された Object 引数が表されたクラス (またはそのサブクラス) のインスタンスである場合、このメソッドは true を返します。それ以外の場合は false を返します。この Class オブジェクトが配列クラスを表す場合、指定された Object 引数を恒等変換または拡大参照変換によって配列クラスのオブジェクトに変換できる場合、このメソッドは true を返します。それ以外の場合は false を返します。この Class オブジェクトがインターフェイスを表す場合、指定された Object 引数のクラスまたはスーパークラスがこのインターフェイスを実装していれば、このメソッドは true を返します。それ以外の場合は false を返します。この Class オブジェクトがプリミティブ型を表す場合、このメソッドは false を返します。

(強調追加)


プリミティブ型を使用しなくなったため、編集は機能します。どちらの場合も、オブジェクトとして渡すことができるよう
に、コンパイラは自動ボックス化します。42

以前のように、最初の呼び出しは効果がありません。
2 番目の呼び出しは、ボックス化された整数が実際にIntegerクラスのインスタンスであることを確認し、それを返します。

于 2013-07-11T15:02:15.073 に答える