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 的所有了解都是它的边界,它可能不知道(除了显式扩展 Object 和 null 类型的 super)。因此,运行时的有效转换是 (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

不会有任何 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() 转换为 return (Number)o;。温你写

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

你会得到一个 ClassCastException,但不是在 cast-method 中,而是在分配给 s 时。

因此,我确实认为,您的“T”不仅仅是“T”,而是“T extends Something”。所以你可以检查:

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 你也许可以在 Class 上使用 isAssignableFrom 方法

于 2008-10-09T16:35:08.190 回答