基于Android Studio和@NonNull/@Nullable注解的Android静态检查实践

前言

前段时间,我发现业务代码中有许多疑似多余的空(null)检查,为什么说是疑似呢?

师傅曾说过:
当你发现一个问题的时候,先别太早下结论,首先确定它是不是个问题,再确定问题的本质,最后由此想出解决方法。
程序员本质上也就是干这两件事,发现问题和解决问题。

故全文围绕这两个问题展开:

  1. 多余的空检查是什么,为什么?
  2. 怎么样避免多余或遗漏的空检查?

AOSP和JDK的代码实践可算是千锤百炼,通过分析和总结归纳,我比较认可的以下方式:

  1. 在私有或包内访问域的方法参数,使用基于Android Studio和@NonNull/@Nullable注解的Android静态检查方法,表明方法是否处理null参数,提升合作效率和代码语义。
  2. 在公有的方法参数(如SDK的API方法),使用正常的空检查,能处理的情况提前返回,不能处理的情况直接抛出IllegalArgumentException,由调用者负责处理。

最后,我们再简单谈谈其他空检查的注解和Android Studio的静态检查工具的其他用法。

问题三连:多余空检查是什么,为什么,怎么样?

代码源于现实生活,让我们举个栗子。

多余的空检查就像坐地铁过安检,收益是需要权衡的。
多次安检固然比较安全,但是也会带来效率上的开销。
一次检查基本上可以拦截大部分问题,后续检查的收益就比较低了。

每一句代码都是需要深思熟虑后才去写的。早期写代码大家可能就是报着“多做无害”的心态,反正不会崩溃。这样容易写出很多冗余代码,最终导致代码腐烂。
多余空检查的开销我没有仔细研究过,应该就是一两个计算机指令,最终换算成CPU时钟周期的计算,在当前CPU性能普遍比较高的今天,也不在话下,只能说,这么做很不极客Geek。

如何避免多余的空检查?

言归正传,如何避免多余的空检查,首先需要知道需要检查的内容,基本上就是外部输入参数或者外部函数返回值,而相对地,不太需要检查的是内部的参数和函数返回值。

  1. 外部入参和返回值处理:
    外部入参和返回值都属于外部输入,跨越信任边界,可视为来源不可信,必须校验其合法性。在入参明显与函数职责不合法,可直接返回IllegalArgumentException,认为这是程序员的逻辑错误,比如对拷贝数组的函数传入null,null参数不在拷贝数组的函数处理范围内,传入null是要找茬?
  2. 内部的参数和函数返回值处理:
    我们不能明确或要求每个函数都处理非空的入参,或者返回值为非空,那么就需要使用额外的方式,约定函数的信息,在Java中,一种比注释更好的方式是注解。

下面主要介绍,基于@NonNull/@Nullable注解以及配合Android Studio的静态检查工具,形成了程序的“约定”。

主要思路

  1. 使用android.annotation或android.support.annotation包下面的@NonNull和@Nullable,对方法或参数进行注解。
  2. 使用Android Studio的inspection静态检查工具,在编码期进行静态检查,及时发现不合理的冗余检查或遗漏检查。

优缺点

  • 优点:

    • 提前发现问题:在编码期就能及时发现不合理的冗余检查或遗漏检查,成本较低。
    • 开销小:@NonNull和@Nullable为源码注解,在编译期就会被编译期无视,不增加运行时开销。
  • 缺点:

    • 约束力较差:仅仅以静态扫描的告警形式表现,而不是编译时error,约束力较弱。
    • 依赖Android Studio:依赖于体量较大的IDE,且需要团队成员均使用才能发挥较好的效果。如果能有独立的命令行lint工具,就最好不过。

配置方法

  1. 导入对应的annotation包: 在APP侧,需要增加对Android support包的依赖;在framework开发中,可以直接使用android.annotation包。

  2. 在Analyze -> Inspection Code,配置inspection静态扫描工具对应的注解类为android.annotation或android.support.annotation包的注解,如下图所示:

配置注解类.png
inpection扫描配置.jpg

自定义注解类.png
  1. 在编码中,通过选择自定义的规则,扫描文件或者文件夹就可以得到扫描报告,并进行快速修改,如下图所示:
NonNull传参.jpg
NonNull检查.jpg
扫描结果.jpg

扩展杂谈

从上文Android Studio的配置可以看出两点:

  1. 其实有其他null检查的注解方式,如Jetbrain提供的注解和Java提供的注解等可以选择;
  2. inspection静态扫描不仅支持null扫描,还有其他非常丰富的规则集可以运用到日常的代码开发中。

这里先做简单地介绍,后面有机会统一学习和实践后再做详细探讨。

  • Android Studio由Jetbrain公司开发,被Google收购,提供了org.jetbrain.annotation注解,搭配Analyze -> infery nullibility功能进行使用,但需要导入org.jetbrain的jar包。
  • java提供了javax.validation.annotation,但不在Android支持的API范围内(Android对Java的包是有选择的引入,特别是javax扩展包,这里不做详解),和JSR305库提供注解,同样需要额外导入jar包。
  • inspection静态扫描工具非常好用,规则配置非常灵活,且可以导入导出配置文件,适合团队使用,后面会分享具体的配置细节。

个人实践总结和心得

  1. 工具只是辅助工具,不要过度依赖工具,最后还是得根据实际情况,由开发者进行判断。毕竟工具只是为了解决人类在某些方面脑力有限而做出来的工具,像调用栈和参数这种东西,人脑也记不了几层。
  2. 越早发现问题成本越低。比起在调试、测试、Beta、上线商用时被发现问题,编码期发现和解决问题的成本简直不要太低,差了好几个数量级呀。所以越早发现问题成本是最低的,防患于未然,做扁鹊大哥吧。
  3. 敬佩Google以开发者为核心的生态布局。在Android开发中,Google的套件,如Android Studio的强大功能(跟它的卡和吃内存是有关系的),framework开发用到的Gerrit(代码检视平台)和repo(多代码仓操作脚本)等等,实在是让人觉得伟大。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容