Java 如何捕获 ClassCastException?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/186917/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:04:09  来源:igfitidea点击:

How do I catch ClassCastException?

javaexceptionexception-handling

提问by yanchenko

I'm trying to catch a ClassCastException when deserializing an object from xml.

从 xml 反序列化对象时,我试图捕获 ClassCastException。

So,

所以,

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

And yet this won't as the exception doesn't get caught. What would you suggest?

然而这不会因为异常不会被捕获。你有什么建议?

采纳答案by Tom Hawtin - tackline

The code in the question should give you an unchecked cast warning. Listen to -Xlint.

问题中的代码应该给你一个未经检查的强制转换警告。听 -Xlint。

All the compiler knows about T is its bounds, which it probably doesn't have (other than explicitly extending Object and a super of the null type). So effectively the cast at runtime is (Object) - not very useful.

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

What you can do is pass in an instance of the Class of the parameterised type (assuming it isn't generic).

您可以做的是传入参数化类型的类的实例(假设它不是通用的)。

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) {
            ...
        }
    }
}

Or as a generic method:

或者作为通用方法:

    public <T> T restore(Class<T> clazz, String from) {
        ...
        try {
            restoredItem = clazz.cast(decoder.readObject());
            ...

回答by yanchenko

Well, I can't use instanceofoperator as the method is a parametrized one:

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

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

And generics in Java are compile-time only.

Java 中的泛型仅在编译时可用。

回答by Tobias Schulte

There will not be any ClassCastException, except when your T has some base:

不会有任何 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;
    }
}

In the above example, there will be no ClassCastException in the first 5 calls to cast and castBaseNumber. Only the 6th call throws a ClassCastException, because the compiler effectively translates the cast() to return (Object) o and the castBaseNumber() to return (Number)o;. Wenn you write

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

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

You would get a ClassCastException, but not whithin the cast-method, but at the assignment to s.

你会得到一个 ClassCastException,但不是在强制转换方法中,而是在对 s 的赋值中。

Therefore I do think, your "T" is not just "T", but "T extends Something". So you could check:

因此,我确实认为,您的“T”不仅仅是“T”,而是“T 扩展了某物”。所以你可以检查:

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

But this will still lead to an error later, when the you use your class.

但是当你使用你的类时,这仍然会导致错误。

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

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

For this case only Tom's advise might help.

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

回答by John Nilsson

If you can't use instaceof you might be able to use the isAssignableFrom method on Class

如果你不能使用 instaceof 你可以在 Class 上使用 isAssignableFrom 方法