2013-07-11 20 views
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)); 
} 

答えて

3

これが原因型消去の起こります。

実行時に、ジェネリック型パラメータは存在しません。
オブジェクトをジェネリック型パラメータにキャストしても効果がありません。

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


あなたの2番目の呼び出しは、intプリミティブ型のcastメソッドを呼び出します。
オブジェクトはプリミティブ型にキャストできないため、例外がスローされます。

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

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

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

(強調追加)


あなたはもはやプリミティブ型を使用しているので、あなたの編集が機能しません。
どちらの場合でも、コンパイラは、オブジェクトとして渡すことができるように、42を自動抑制します。

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

+0

私は、コードはプリミティブを除いてすべての与えられたクラスで動作すると書いています。オブジェクトをジェネリック型にキャストすることは可能です。次に、オブジェクトをプリミティブにキャストできます。 – m3th0dman

+0

@ m3th0dman:私はそれが不可能だと言っていませんでした。私はそれが実行時に効果がないと言いました。 – SLaks

+0

私は今理解しています。しかし、この種の鋳造法の契約を破ることはありませんか?技術的にはキャストが可能です。 – m3th0dman

関連する問題