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”)注解来禁止警告。 记录你决定在注释中抑制此警告的理由。

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

  1. Effective Java 第三版——7. 消除过期的对象引用

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  2. 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...

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

    版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...

  4. Effective Java 第三版——4. 使用私有构造方法执行非实例化

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

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

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

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

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

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

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

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

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

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

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. java多线程(五)-访问共享资源以及加锁机制(synchronized,lock,voliate)

    对于单线程的顺序编程而言,每次只做一件事情,其享有的资源不会产生什么冲突,但是对于多线程编程,这就是一个重要问题了,比如打印机的打印工作,如果两个线程都同时进行打印工作,那这就会产生混乱了.再比如说, ...

  2. 使用performance monitor 查看 每一个cpu core的cpu time

    使用performance monitor 查看 每一个cpu core的cpu time: 打开performance monitor,添加 counter 如下 运行一段cpu bound 的代码 ...

  3. HTML、CSS、JS 复习——序

    HTML在MVC中担任着M的角色.由HTML组成的节点称之为HTML DOM.要想成为一流的大神,就必须能分分钟建立起一个强大的HTML DOM.而要做到这点,就必须了解甚至精通HTML. CSS在M ...

  4. Java框架之Spring MVC(二)

    一.Spring MVC 验证 JSR 303 是ajvaEE6 中的一项子规范 ,叫 Bean Validation 用于对javaBean中的字段进行校验. 官方的参考实现是: Hibernate ...

  5. 深入理解JVM(三)——配置参数

    JVM配置参数分为三类参数: 1.跟踪参数 2.堆分配参数 3.栈分配参数 这三类参数分别用于跟踪监控JVM状态,分配堆内存以及分配栈内存. 跟踪参数 跟踪参数用于跟踪监控JVM,往往被开发人员用于J ...

  6. Django之路由分发系统

    web的基本工作流程 首先,我们先来思考一下我们平常在上网浏览网页时候的场景,大致就是打开一个web浏览器,输入某一个网站的地址,然后转到该网址,在浏览器中得到该网址的页面.从这个场景中我们可以抽象出 ...

  7. install brew cask

    os x install brew cask '/usr/../../brew-cask.rb' does not exist brew 已安装完毕,安装brew cask brew install ...

  8. 从 0 到 1,Java Web 网站架构搭建的技术演进

    初始搭建 最开始,就是各种框架一搭,然后扔到 Tomcat 容器中跑,这时候我们的文件.数据库.应用都在一个服务器上. 服务分离 随着系统的上线,用户量也会逐步上升,很快一台服务器已经满足不了系统的负 ...

  9. IdentityServer Topics(5)- 使用第三方登录

    ASP.NET Core有一个灵活的方式来处理外部认证. 这包括几个步骤. 如果您使用的是ASP.NET Identity,则许多底层技术细节对您而言都是隐藏的. 建议您还阅读Microsoft文档并 ...

  10. element-ui,router.push到其他路由,菜单栏不会高亮对应的路由

    使用饿了吗的路由,使用this.$router.push({path: ''})跳到其他的路由,菜单不会高亮. 如图所示,点击图上三个位置,需要使用this.$router.push({path: ' ...