什么是未经检查的演员阵容以及如何检查它?

发布于 2024-08-29 17:27:27 字数 87 浏览 10 评论 0原文

我想我明白未经检查的演员意味着什么(从一种不同类型的演员到另一种类型的演员),但是“检查”演员意味着什么?如何检查强制转换以避免 Eclipse 中出现此警告?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清醇 2024-09-05 17:27:27

详细说明 Peter 所写的内容:

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

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

第 3 行未经检查的警告表明编译器无法保证类型安全,即稍后可能会发生意外的 ClassCastException。事实上,这发生在第 4 行,它执行隐式转换。

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 ClassCastException due to an incorrect assumption regarding the type parameter. For example:

    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.

你的往事 2024-09-05 17:27:27

未经检查的强制转换意味着您正在(隐式或显式)从泛型类型强制转换为非限定类型,或者反之亦然。例如这一行

Set<String> set = new HashSet();

会产生这样的警告。

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

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

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

当然,消除警告并不总是像上面的代码那么容易。如果没有看到你的代码,就无法知道如何保证它的安全。

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:

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 ClassCastException at 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 ClassCastException at 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.

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.

薔薇婲 2024-09-05 17:27:27

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

以下是基于第三版的考虑类型安全异构容器部分的示例。 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);
    }

}

如果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)

但如果 retrieve() 使用检查强制转换 -
key.cast(map.get(key)) - 运行此程序将导致在 key.cast(map.get(key))< 处发生 ClassCastException /code> 行,因为检查后的强制转换会发现类型错误并抛出异常。 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)

看起来差别不大,但在未经检查的强制转换的情况下,String 成功进入 List< ;整数>。在现实世界的应用中,这样做的后果可能......嗯,很严重。在检查演员表的情况下,尽早发现类型不匹配。


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

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

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


为了完整起见,这个答案涉及 Eclipse 的具体细节。

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 containers section of the 3rd ed. of "Effective Java" by Joshua Bloch, but the container class is intentionally broken - it stores and returns the wrong type:

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 ClassCastException occurring at Integer i = ints.get(0) line. The retrieve() method will complete because the actual type was not checked at runtime:

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 ClassCastException occurring 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:

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 String successfully 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.


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.

As Joshua Bloch put it,

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


For the sake of completeness, this answer deals with the Eclipse specifics.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文