effective-Java/ch05泛型/27.消除非检查警告.md
2019-11-21 19:59:07 +08:00

3.2 KiB
Raw Blame History

消除非检查警告

使用泛型编程时,会看到许多编译器警告:

  • 未经检查的强制转换警告
  • 未经检查的方法调用警告
  • 未经检查的参数化可变长度类型警告
  • 未经检查的转换警告

你使用泛型获得的经验越多,获得的警告越少,但不要期望新编写的代码能够干净地编译。

示例代码Item27Example01.java

// 警告HashSet是原始类型。 泛型类型HashSet <E>的引用应参数化。
new HashSet(); 

// 进行指示修正,让警告消失。
// 请注意,实际上并不需要指定类型参数,只是为了表明它与 Java 7 中引入的钻石运算符(「<>」)一同出现。
new HashSet<>(); 

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

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

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

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

// 使用 SuppressWarnings 注解声明单个局部变量
@SuppressWarnings({"rawtypes", "unchecked"})
Set<String> set = new HashSet(); 

示例代码Item27Example02.java:最小化未经检查的警告被抑制的范围。

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

每个未经检查的警告代表在运行时出现 ClassCastException 异常的可能性。 尽你所能消除这些警告。

如果无法消除未经检查的警告,并且可以证明引发该警告的代码是安全类型的,则可以在尽可能小的范围内使用 @SuppressWarnings(“unchecked”) 注解来禁止警告。 记录你决定在注释中抑制此警告的理由。