10

xml からオブジェクトを逆シリアル化するときに ClassCastException をキャッチしようとしています。

そう、

try {
    restoredItem = (T) decoder.readObject();
} catch (ClassCastException e){
    //don't need to crash at this point,
   //just let the user know that a wrong file has been passed.
}

それでも、例外がキャッチされないため、これは行われません。何を提案しますか?

4

4 に答える 4

11

問題のコードは、チェックされていないキャストの警告を表示するはずです。-Xlint を聞いてください。

コンパイラが T について知っているのはその境界だけであり、それはおそらく持っていません (明示的にオブジェクトを拡張し、null 型のスーパーを除いて)。したがって、実質的に実行時のキャストは (Object) であり、あまり役に立ちません。

できることは、パラメーター化された型の Class のインスタンスを渡すことです (ジェネリックではない場合)。

class MyReader<T> {
    private final Class<T> clazz;
    MyReader(Class<T> clazz) {
        if (clazz == null) {
            throw new NullPointerException();
        }
        this.clazz = clazz;
    }
    public T restore(String from) {
        ...
        try {
            restoredItem = clazz.cast(decoder.readObject());
            ...
            return restoredItem;
        } catch (ClassCastException exc) {
            ...
        }
    }
}

または一般的な方法として:

    public <T> T restore(Class<T> clazz, String from) {
        ...
        try {
            restoredItem = clazz.cast(decoder.readObject());
            ...
于 2008-10-09T12:36:44.850 に答える
3

Tにベースがある場合を除いて、ClassCastExceptionは発生しません。

public class GenericsTest
{
    public static void main(String[] args)
    {
        System.out.println(cast(Integer.valueOf(0)));
        System.out.println(GenericsTest.<Long> cast(Integer.valueOf(0)));
        System.out.println(GenericsTest.<Long> cast("Hallo"));

        System.out.println(castBaseNumber(Integer.valueOf(0)));
        System.out.println(GenericsTest.<Long> castBaseNumber(Integer.valueOf(0)));
        System.out.println(GenericsTest.<Long> castBaseNumber("Hallo"));
    }

    private static <T extends Number> T castBaseNumber(Object o)
    {
        T t = (T)o;
        return t;
    }

    private static <T> T cast(Object o)
    {
        T t = (T)o;
        return t;
    }
}

上記の例では、castとcastBaseNumberへの最初の5回の呼び出しでClassCastExceptionは発生しません。コンパイラはcast()を効果的に変換して(Object)oを返し、castBaseNumber()を(Number)o;に返すため、6番目の呼び出しのみがClassCastExceptionをスローします。あなたが書くウェン

String s = GenericsTest.<Long> cast("Hallo");

ClassCastExceptionが発生しますが、castメソッドでは発生しませんが、sへの割り当て時に発生します。

したがって、あなたの「T」は「T」だけでなく、「Tは何かを拡張する」と思います。だからあなたはチェックすることができます:

Object o = decoder.readObject();
if (o instanceof Something)
    restoredItem = (T) o;
else 
    // Error handling

ただし、後でクラスを使用すると、エラーが発生します。

public Reader<T extends Number>{...}

Long l = new Reader<Long>("file.xml").getValue(); // there might be the ClassCastException

この場合、トムのアドバイスだけが役立つかもしれません。

于 2008-10-09T12:51:44.320 に答える
0

instanceofメソッドはパラメータ化されたものであるため、演算子を使用することはできません。

public T restore(String from){
...
restoredItem = (T) decoder.readObject();
...
}

また、Javaのジェネリックはコンパイル時のみです。

于 2008-10-09T12:10:08.413 に答える
0

instaceofを使用できない場合は、クラスでisAssignableFromメソッドを使用できる可能性があります

于 2008-10-09T16:35:08.190 に答える