Effective Java 3rd 条目27 消除非受检警告

当你用泛型编程时,你将会看见许多编译器警告:非受检强转警告、非受检方法调用警告、非受检参数化vararg类型警告和非受检转换警告。你多熟悉泛型一些,你将获得更少警告,但是不要期待这些新代码干净利索地编译。

许多非受检警告容易消除。例如,假设你不慎编写如下声明:

Set<Lark> exaltation = new HashSet();

编译器会轻轻地告诉你做错了什么:

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

然后你可以进行指示的改正,使得警告消失。记住,你实际上不需要指定类型参数,仅仅用菱形操作子(diamond operator)(<>)(在Java7引入)表示。然后编译器会推导(infer)正确的实际类型参数(在这个情形中,Lark):

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

一些警告会更加难于清除。这个章节充满了这样警告的例子。当你遇见需要更多思考的警告时,你需要坚持不懈!尽你所能地消除每个非受检警告。如果你消除了所有警告,那么你敢保证你的代码是类型安全,这是一个非常好的事情。这意味着,你不会在运行时遇见ClassCastException,而且它增加了你的信心:你的代码将像预期的一样运行。

如果你不能消除警告,但是你可以证明:引起警告的代码是类型安全的,那时(也只有直到那时)用@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[]

把SuppressWarnings注解放到返回语句上,这是不合法的,因为它不是一个声明[JLS, 9.7]。你可能想把注解放到整个方法上,但是不要这么做。反而,声明一个本地变量来保留返回值,而且注解它的声明,就像如此:

// 为了减少@SuppressWarnings范围而添加本地变量
public <T> T[] toArray(T[] a) {
    if (a.length < size) { 
        // 整个强转是正确的,因为我们创建的这个队列,是和传入的这个是相同类型的,即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")注解在尽可能窄的范围内抑制这个警告。为在注释中抑制警告这个决定,标明基本的阐述。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 使用泛型编程时,会遇到许多编译器警告,如:非受检强制转化警告,非受检方法调用警告,非受检普通数组创建警告,非...
    呼天阔阅读 532评论 0 0
  • 整体Retrofit内容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李头阅读 6,206评论 4 31
  • 医保业务分拆独立 在整合互联网金融板块的同时,另一个被马明哲视为未来核心战略的健康医疗板块也正在重整架构。 记者从...
    leook阅读 231评论 0 1
  • 假期来临,很多平常忙于工作的MM终于有时间减肥了。但在家该如何有效减肥似乎还没有具体的规划,既然如此,不如来跟小编...
    我会叫的阅读 204评论 0 0
  • 青春的坎坷有什么意味?是低调的华丽,还是明媚的忧伤?是流星划过刹那的许诺,还是芳华散尽时的叹息?其实不过是生命的滴...
    丑小鹅阅读 380评论 0 2