当你使用泛型编程时,你将看到许多编译警告:未检查的强制转换警告,未检查的方法调用,未检查的参数化vararg类型警告,以及未检查的转换警告。 使用泛型获得的经验越多,得到的警告就越少,但是不要期望新编写的代码能够干净地编译。
许多未检查的异常很容易消除。比如,假设你意外地编写这段声明:
Set exaltation = new HashSet();
编译器将会温柔地提醒你哪里错了:
image.png
然后你可以根据提示更正,从而警告消失。请注意,你实际上不必指定类型参数,只需要表明它与Java7中引入的菱形操作符(<>)一起存在。编译器将会正确推断实际的类型参数(在这种情况下,类型是Lark):
Set exaltation = new HashSet<>();
如果你不能消除一个警告,但是你可以证明引发警告的代码是类型安全的,那么(只有在那个时候)使用@Suppress Warnings("uncheckded")注释来抑制警告。如果你没有在第一时间证明代码是类型安全的就抑制警告了,你就给了自己一个错误的安全感。代码可以编译而不发出任何警告,但是它仍然可以在运行时抛出ClassCastException。但是,如果你忽略了你知道是安全的未经检查的警告(而不是抑制它们),那么你将不会注意到什么时候出现了新的警告,它代表了一个真正的问题。新的警告将在你没有沉默的所有虚假警报中消失
SuppressWarnings注解可以在任何声明上使用,从一个局部的本地变量声明到一整个类。始终在最小范围中使用SuppressWarnings注解。通常,这将是一个变量声明或一个非常小的方法或构造方法。永远别再一整个类中使用SuppressWarnings。这么做会掩盖关键的警告。
如果你发现自己在多行长的方法或构造方法上使用了SuppressWarnings注解,你可以将其转移到局部变量声明中。你可能需要声明一个新的局部变量,但是这是值得的。例如,考虑这个toArray方法,它来自ArrayList。
image.png
如果你编译ArrayList,该方法将会生成这个警告:
image.png
在return语句上添加SuppressWarnings注解是非法的,因为它不是一个声明 [JLS, 9.7]你可能会尝试将注释放在整个方法上,但是不要这么做。相反,声明一个局部变量以保存返回值并注释其声明,如下所示:
image.png
生成的方法可以干净地编译,并最小化未检查的警告被抑制的范围。
每次你使用@SuppressWarnings(“unchecked”)注解,需要添加注释说明为什么这么做是安全的。浙江帮助别人理解代码,更重要的是,它将降低有人修改代码的可能性,而导致计算变得不安全。如果你觉得很难写出这样的注释,那就继续思考。你可能最终会发现未经检查的操作毕竟是不安全的。
总之,未经检查的警告是重要的。不要忽视它们。每个未检查警告代表了一个在运行时潜在的ClassCastException危险。尽你最大的努力来消除这些警告。如果你不能消除未经检查的警告,并可以证明引发该警告的代码是类型安全,请在尽可能窄的范围内使用@SuppressWarnings("unChecking")注解来抑制警告。并在注释中记录你决定抑制警告的理由。
本文写于2019.6.7,历时1天
网友评论