Java 什么是未经检查的演员表,我该如何检查?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2693180/
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-13 10:53:59  来源:igfitidea点击:

What is unchecked cast and how do I check it?

javaeclipsecastingunchecked

提问by SIr Codealot

I think I get what unchecked cast means (casting from one to another of a different type), but what does it mean to "Check" the cast? How can I check the cast so that I can avoid this warning in Eclipse?

我想我明白了 unchecked cast 的意思(从一个不同类型的转换到另一个类型),但是“检查”转换是什么意思?如何检查演员表,以便在 Eclipse 中避免此警告?

采纳答案by Péter T?r?k

Unchecked cast means that you are (implicitly or explicitly) casting from a generic type to a nonqualified type or the other way around. E.g. this line

未经检查的强制转换意味着您(隐式或显式)从泛型类型转换为非限定类型,或者相反。例如这条线

Set<String> set = new HashSet();

will produce such a warning.

会产生这样的警告。

Usually there is a good reason for such warnings, so you should try to improve your code instead of suppressing the warning. Quote from Effective Java, 2nd Edition:

通常此类警告是有充分理由的,因此您应该尝试改进代码而不是抑制警告。引自 Effective Java,第 2 版:

Eliminate every unchecked warning that you can.If you eliminate all warnings, you are assured that your code is typesafe, which is a very good thing. It means that you won't get a ClassCastExceptionat runtime, and it increases your confidence that your program is behaving as you intended.

If you can't eliminate a warning, and you can prove that the code that provoked the warning is typesafe, then (and only then) suppress the warning with an @SuppressWarnings("unchecked")annotation. If you suppress warnings without first proving that the code is typesafe, you are only giving yourself a false sense of security. The code may compile without emitting any warnings, but it can still throw a ClassCastExceptionat runtime. If, however, you ignore unchecked warnings that you know to be safe (instead of suppressing them), you won't notice when a new warning crops up that represents a real problem. The new warning will get lost amidst all the false alarms that you didn't silence.

尽可能消除所有未经检查的警告。如果您消除了所有警告,您就可以确信您的代码是类型安全的,这是一件非常好的事情。这意味着您不会ClassCastException在运行时得到 a ,并且它增加了您对程序按预期运行的信心。

如果您无法消除警告,并且您可以证明引发警告的代码是类型安全的,那么(并且只有这样)使用@SuppressWarnings("unchecked")注释抑制警告。如果你在没有首先证明代码是类型安全的情况下抑制警告,你只会给自己一种错误的安全感。代码可以编译而不会发出任何警告,但它仍然可以ClassCastException在运行时抛出 a 。但是,如果您忽略您知道是安全的未经检查的警告(而不是抑制它们),您将不会注意到何时出现代表真正问题的新警告。新警告将在您没有静音的所有误报中消失。

Of course, it is not always as easy to eliminate warnings as with the code above. Without seeing your code, there is no way to tell how to make it safe though.

当然,消除警告并不总是像上面的代码那样容易。如果没有看到您的代码,就无法知道如何使其安全。

回答by Eyal Schneider

To elaborate on what Peter wrote:

详细说明彼得所写的内容:

Casts from non-generic types to generic types may work just fine at runtime, because the generic parameters are erased during compilation, so we are left with a legitimate cast. However, the code may fail later with an unexpected ClassCastExceptiondue to an incorrect assumption regarding the type parameter. For example:

从非泛型类型到泛型类型的转换在运行时可能工作得很好,因为泛型参数在编译期间被删除,所以我们留下了一个合法的转换。但是,ClassCastException由于对类型参数的假设不正确,代码可能会在稍后出现意外失败。例如:

    List l1 = new ArrayList();
    l1.add(33);
    List<String> l2 = (List<String>) l1;
    String s = l2.get(0);

The unchecked warning at line 3 indicates that the compiler is not able to guarantee type safety, in the sense that an unexpected ClassCastException may occur at a later point. Indeed, this happens at line 4, which performs an implicit cast.

第 3 行的 unchecked 警告表明编译器无法保证类型安全,因为稍后可能会发生意外的 ClassCastException。事实上,这发生在第 4 行,它执行了一个隐式转换。

回答by jihor

An unchecked cast, as opposed to checked cast, does not check type safety at runtime.

与已检查的强制转换相反,未检查的强制转换不会在运行时检查类型安全。

Here's an example based on the Consider typesafe heterogenous containerssection of the 3rd ed. of "Effective Java" by Joshua Bloch, but the container class is intentionally broken - it stores and returns the wrong type:

这是基于Consider typesafe heterogenous containers第 3 版部分的示例。Joshua Bloch 的“Effective Java”,但容器类被故意破坏 - 它存储并返回错误的类型:

public class Test {

    private static class BrokenGenericContainer{
        private final Map<Class<?>, Object> map= new HashMap<>();

        public <T> void store(Class<T> key, T value){
            map.put(key, "broken!"); // should've been [value] here instead of "broken!"
        }

        public <T> T retrieve(Class<T> key){
//          return key.cast(map.get(key)); // a checked cast 
            return (T)map.get(key);        // an unchecked cast
        }

    }

    public static void main(String[] args) {
        BrokenGenericContainer c= new BrokenGenericContainer();
        c.store(Integer.class, 42);
        List<Integer> ints = new ArrayList<>();
        ints.add(c.retrieve(Integer.class));
        Integer i = ints.get(0);
    }

}


If the retrieve()uses an unchecked cast-(T)map.get(key)- running this program will lead to ClassCastExceptionoccurring at Integer i = ints.get(0)line. The retrieve()method will complete because the actual type was not checked at runtime:


如果retrieve()使用未经检查的强制转换- (T)map.get(key)- 运行此程序将导致ClassCastException发生Integer i = ints.get(0)在线。该retrieve()方法将完成,因为在运行时未检查实际类型:

Exception in thread "main" 
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Test.main(Test.java:27)


But if the retrieve()uses a checked cast- key.cast(map.get(key))- running this program will lead to ClassCastExceptionoccurring at key.cast(map.get(key))line, because the checked cast will find out that the type is wrong and throw the exception. The retrieve()method will not complete:


但是,如果retrieve()使用了检查转换- key.cast(map.get(key))-运行此程序将导致ClassCastException在发生key.cast(map.get(key))行,因为检查转换会发现,该类型是错误的,抛出异常。该retrieve()方法不会完成:

Exception in thread "main" java.lang.ClassCastException: 
                                          Cannot cast java.lang.String to java.lang.Integer
    at java.lang.Class.cast(Class.java:3369)
    at Test$BrokenGenericContainer.retrieve(Test.java:16)
    at Test.main(Test.java:26)

Little difference it may seem, but in the case with the unchecked cast, a Stringsuccessfully made its way into a List<Integer>. In real world applications, consequences of this may be... well, severe. In case with the checked cast, the type mismatch was discovered as early as possible.

看起来差别不大,但在未经检查的演员表的情况下, aString成功地进入了List<Integer>. 在现实世界的应用中,其后果可能是……好吧,严重。如果使用已检查的强制转换,则会尽早发现类型不匹配。



To avoid the unchecked casts warning, @SuppressWarnings("unchecked")can be used, if the programmer is really sure the method is in fact safe. The better alternative is to use generics and checked casts when possible.

为了避免 unchecked casts 警告,@SuppressWarnings("unchecked")可以使用,如果程序员真的确定该方法实际上是安全的。更好的选择是在可能的情况下使用泛型和检查强制转换。

As Joshua Bloch put it,

正如约书亚·布洛赫所说,

...unchecked warnings are important. Don't ignore them.

...未经检查的警告很重要。不要忽视它们。



For the sake of completeness, thisanswer deals with the Eclipse specifics.

为完整起见,答案涉及 Eclipse 细节。