美文网首页
项目27:消除未经检查的警告

项目27:消除未经检查的警告

作者: rabbittttt | 来源:发表于2019-06-07 16:15 被阅读0次

    ITEM 27: ELIMINATE UNCHECKED WARNINGS
      使用泛型编程时,您将看到许多编译器警告: 未经检查的强制转换警告、未经检查的方法调用警告、未经检查的参数类型警告和未经检查的转换警告。使用泛型获得的经验越多,得到的警告就越少,但是不要期望新编写的代码能够干净地编译。
      许多未经检查的警告很容易消除。例如,假设您不小心编写了以下声明:
    Set<Lark> exaltation = new HashSet();
      编译器会温柔地提醒你做错了什么:
    “Venery.java:4: warning: [unchecked] unchecked conversion Set<Lark> exaltation = new HashSet(); required: Set<Lark> found: HashSet”
      我们应该按照指示更正,使警告消失。注意,实际上不需要指定类型参数,只需要指出它与在 Java 7 中引入的 diamond 操作符 (<>) 一起出现。编译器将推断正确的实际类型参数(在本例中为Lark):
    Set<Lark> exaltation = new HashSet<>();
      有些警告更难消除。本章充满了此类警告的例子。当你得到需要一些思考的警告时,坚持下去!尽可能消除所有未经检查的警告。如果消除了所有警告,就可以确保代码是类型安全的,这是一件非常好的事情。这意味着您不会在运行时获得ClassCastException,并且它增加了您的信心,使您相信您的程序将按照您的意愿运行。
      如果不能消除警告,但是可以证明触发警告的代码是 typesafe,那么(而且只有在这种情况下)使用 @SuppressWarnings(“unchecked”) 注释来抑制警告。如果您在没有首先证明代码是类型安全的情况下就抑制了警告,那么您就给了自己一种错误的安全感。代码可以在编译时不发出任何警告,但仍然可以在运行时抛出ClassCastException。但是,如果忽略未检查的安全警告(而不是抑制它们),就不会注意到什么时候出现了一个表示真正问题的新警告。新的警告将在你没有保持沉默的所有错误警报中消失。
      SuppressWarnings 注释可以用于任何声明,从单个局部变量声明到整个类。始终在尽可能小的范围内使用 SuppressWarnings 注释。通常这将是一个变量声明或一个非常短的方法或构造函数。永远不要在整个类上使用 SuppressWarnings。这样做可能会掩盖严重的警告。
      如果您发现自己在一个方法或构造函数上使用了 SuppressWarnings 注释,并且该注释的长度超过一行,那么您可以将它移动到一个局部变量声明上。您可能需要声明一个新的局部变量,但这是值得的。例如,考虑这个 toArray 方法,它来自 ArrayList:

    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[]”
      在 return 语句上放置一个 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”) 注释在尽可能小的范围内禁止警告。在评论中记录下你决定取消警告的理由。

    相关文章

      网友评论

          本文标题:项目27:消除未经检查的警告

          本文链接:https://www.haomeiwen.com/subject/jjzmxctx.html