我如何捕获ClassCastException?

时间:2008-10-09 11:56:08

标签: java exception exception-handling

我正在尝试从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 个答案:

答案 0 :(得分:11)

问题中的代码应该为您提供未经检查的投射警告。听听-Xlint。

所有编译器都知道T是它的边界,它可能没有(除了显式扩展Object和null类型的super)。因此,运行时的强制转换是(对象) - 不是很有用。

您可以做的是传入参数化类型的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());
            ...

答案 1 :(得分:3)

不会有任何ClassCastException,除非你的T有一些基础:

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;
    }
}

在上面的例子中,在前5次调用cast和castBaseNumber时没有ClassCastException。只有第6次调用才会抛出ClassCastException,因为编译器有效地将cast()转换为return(Object)o,并将castBaseNumber()转换为返回(Number)o;。你写的文

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

对于这种情况,只有汤姆的建议可能有所帮助。

答案 2 :(得分:0)

好吧,我不能使用instanceof运算符,因为该方法是参数化的:

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

Java中的泛型只是编译时间。

答案 3 :(得分:0)

如果你不能使用instanceof,你可以在Class

上使用isAssignableFrom方法