Effective Java 第三版——27. 消除非检查警告

Tips
《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化。
在这里第一时间翻译成中文版。供大家学习分享之用。

27. 消除非检查警告

使用泛型编程时,会看到许多编译器警告:未经检查的强制转换警告,未经检查的方法调用警告,未经检查的参数化可变长度类型警告以及未经检查的转换警告。 你使用泛型获得的经验越多,获得的警告越少,但不要期望新编写的代码能够干净地编译。

许多未经检查的警告很容易消除。 例如,假设你不小心写了以下声明:

Set<Lark> exaltation = new HashSet();

编译器会提醒你你做错了什么:

Venery.java:4: warning: [unchecked] unchecked conversion
        Set<Lark> exaltation = new HashSet();
                               ^
  required: Set<Lark>
  found:    HashSet

然后可以进行指示修正,让警告消失。 请注意,实际上并不需要指定类型参数,只是为了表明它与Java 7中引入的钻石运算符("<>")一同出现。然后编译器会推断出正确的实际类型参数(在本例中为Lark):

Set<Lark> exaltation = new HashSet<>();

但一些警告更难以消除。 本章充满了这种警告的例子。 当你收到需要进一步思考的警告时,坚持不懈! 尽可能地消除每一个未经检查的警告。 如果你消除所有的警告,你可以放心,你的代码是类型安全的,这是一件非常好的事情。 这意味着在运行时你将不会得到一个ClassCastException异常,并且增加了你的程序将按照你的意图行事的信心。

如果你不能消除警告,但你可以证明引发警告的代码是类型安全的,那么(并且只能这样)用@SuppressWarnings(“unchecked”)注解来抑制警告。 如果你在没有首先证明代码是类型安全的情况下压制警告,那么你给自己一个错误的安全感。 代码可能会在不发出任何警告的情况下进行编译,但是它仍然可以在运行时抛出ClassCastException异常。 但是,如果你忽略了你认为是安全的未经检查的警告(而不是抑制它们),那么当一个新的警告出现时,你将不会注意到这是一个真正的问题。 新出现的警告就会淹没在所有的错误警告当中。

SuppressWarnings注解可用于任何声明,从单个局部变量声明到整个类。 始终在尽可能最小的范围内使用SuppressWarnings注解。 通常这是一个变量声明或一个非常短的方法或构造方法。 切勿在整个类上使用SuppressWarnings注解。 这样做可能会掩盖重要的警告。

如果你发现自己在长度超过一行的方法或构造方法上使用SuppressWarnings注解,则可以将其移到局部变量声明上。 你可能需要声明一个新的局部变量,但这是值得的。 例如,考虑这个来自ArrayList的toArray方法:

public <T> T[] toArray(T[] a) {
    if (a.length < size)
       return (T[]) Arrays.copyOf(elements, size, a.getClass());
    System.arraycopy(elements, 0, a, 0, size);
    if (a.length > size)
       a[size] = null;
    return a;
}

如果编译ArrayList类,则该方法会生成此警告:
ArrayList.java:305: warning: [unchecked] unchecked cast
       return (T[]) Arrays.copyOf(elements, size, a.getClass());
                                 ^
  required: T[]
  found:    Object[]

在返回语句中设置SuppressWarnings注解是非法的,因为它不是一个声明[JLS,9.7]。 你可能会试图把注释放在整个方法上,但是不要这要做。 相反,声明一个局部变量来保存返回值并标注它的声明,如下所示:

// Adding local variable to reduce scope of @SuppressWarnings
public <T> T[] toArray(T[] a) {
    if (a.length < size) {
        // This cast is correct because the array we're creating
        // is of the same type as the one passed in, which is T[].
        @SuppressWarnings("unchecked") T[] result =
            (T[]) Arrays.copyOf(elements, size, a.getClass());
        return result;
    }
    System.arraycopy(elements, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

所产生的方法干净地编译,并最小化未经检查的警告被抑制的范围。

每当使用@SuppressWarnings(“unchecked”)注解时,请添加注释,说明为什么是安全的。 这将有助于他人理解代码,更重要的是,这将减少有人修改代码的可能性,从而使计算不安全。 如果你觉得很难写这样的注释,请继续思考。 毕竟,你最终可能会发现未经检查的操作是不安全的。

总之,未经检查的警告是重要的。 不要忽视他们。 每个未经检查的警告代表在运行时出现ClassCastException异常的可能性。 尽你所能消除这些警告。 如果无法消除未经检查的警告,并且可以证明引发该警告的代码是安全类型的,则可以在尽可能小的范围内使用 @SuppressWarnings(“unchecked”)注解来禁止警告。 记录你决定在注释中抑制此警告的理由。

原文地址:https://www.cnblogs.com/IcanFixIt/p/8375780.html

时间: 2024-11-05 15:56:15

Effective Java 第三版——27. 消除非检查警告的相关文章

《Effective Java 第三版》新条目介绍

前言 从去年的3月份起我就在开始读<Effective Java 第二版>,当然,我读的是中文版的:可能是我理解能力还不行,对于书中的内容总是感觉理解困难:就拿第一章的内容「创建和销毁对象」来说吧,这是我读的次数最多的一章,想必原因大家也是明白的,每次我读不下去的时候,我就从头开始读,所以,现在我对这本书的第一章是最为熟悉的了.后来,有一次我上网看到有网友说这本书确实和绝大部分的翻译书籍一样,对于有些原文中的内容翻译的不是很流畅,所以会导致阅读的人感觉难以理解:于是,我就斗胆下了本英文的原版来

Effective Java 第三版——10. 重写equals方法时遵守通用约定

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 10. 重写equals方法时遵守通用约定 虽然Object是一个具体的类,但它主要是为继承而设计的.它的所有非 final方法(equals.hashCode.toStr

Effective Java 第三版——18. 组合优于继承

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 18. 组合优于继承 继承是实现代码重用的有效方式,但并不总是最好的工具.使用不当,会导致脆弱的软件. 在包中使用继承是安全的,其中子类和父类的实现都在同一个程序员的控制之

Effective Java 第三版——19. 如果使用继承则设计,并文档说明,否则不该使用

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 19. 如果使用继承则设计,并文档说明,否则不该使用 条目 18中提醒你注意继承没有设计和文档说明的"外来"类的子类化的危险. 那么为了继承而设计和文档

Effective Java 第三版——29. 优先考虑泛型

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 29. 优先考虑泛型 参数化声明并使用JDK提供的泛型类型和方法通常不会太困难. 但编写自己的泛型类型有点困难,但值得努力学习. 考虑条目 7中的简单堆栈实现: // Ob

Effective Java 第三版——34. 使用枚举类型替代整型常量

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. Java支持两种引用类型的特殊用途的系列:一种称为枚举类型的类和一种称为注解类型的接口. 本章讨论使用这些类型系列的最佳实践. 34. 使用枚举类型替代整型常量 枚举是其合

5. Effective Java 第三版——使用依赖注入取代硬连接资源

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 5. 使用依赖注入取代硬连接资源(hardwiring resources) 许多类依赖于一个或多个底层资源.例如,拼写检查器依赖于字典.将此类类实现为静态实用工具类并不少

Effective Java 第三版——13. 谨慎地重写 clone 方法

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 13. 谨慎地重写 clone 方法 Cloneable接口的目的是作为一个mixin接口(条目 20),公布这样的类允许克隆.不幸的是,它没有达到这个目的.它的主要缺点是

Effective Java 第三版——14.考虑实现Comparable接口

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. ?14.考虑实现Comparable接口 与本章讨论的其他方法不同,compareTo方法并没有在Object类中声明. 相反,它是Comparable接口中的唯一方法.