Java | FindBugs JSR305 与 Guava Preconditions

前言

每个开发者都有自己的一套通用代码库,里面封装了一些 Java API 的便捷方法,主要是为了避免模板代码的编写。但在很多时候,由于时间已久,你可能忘了当初定下的规则,以至于给方法传递错误的参数,在不恰当的时机调用方法,不对返回值进行空值检测就直接使用,等等。你必须为此承担潜在风险,甚至付出巨大代价。

正文

鉴于以上种种,我们来讨论 如何优化通用代码库,避免底层 bug 带来的潜在风险。

方案一:jsr305 + findbugs

findbugs 是一套成熟的 bug 解决方案,通过 jsr305 提供的注解类,适合在底层通用代码库中使用。

提示:大部分情况下,使用 @Nonnull@Nullable 这两个注解较多。

jsr305 使用示例:

注意:以上所有注解只是示例,并不具备实际意义,请不要效仿。

关于 @Nonnull 注解的细节:

解释:标记的元素不能为 Null。它用在字段上时,表示对象构造完成后,字段不能为 Null;用在方法上时,将应用于方法返回值的检测。

findbugs 使用示例:

猜测:静态代码检测工具是对字节码的检测,所以源代码看不出来问题,但最终会在字节码中现行。

基于以上猜测,咱们从 TimeHelper.class 文件中寻找最终答案:

因为 DateHelper.formatNormal(value) 方法上加了 @Nonnull 注解,所以第一段逻辑是有检测冗余,而后面两段逻辑被 findbugs 识别为 This method may return a null value, but the method (or a superclass method which it overrides) is declared to return @Nonnull.。我们读 API 文档和源码,得知 DateTimeFormatter.ISO_LOCAL_TIME.format(valueTime) 不会返回 Null 值,而 findbugs 出现错误提示的原因,暂时猜测是我们没有对 format 方法返回值进行判断,并在为 Null 的情况下提供默认值。

建议
  • 慎用 @Nonnull 注解
    应该移除所有非接口类中的 @Nonnull 注解,接口的实现类可以保留。因此默认情况下,字段、方法返回值、方法参数不为 Null;其他情况下,则按需使用 @Nullable 注解,表示允许传递 Null 值。

  • 手动检测 Null
    在有 @Nonnull 注解的情况下,应该对未知方法(没有相关注解),进行手动检测 Null 值并提供默认值。

以上建议参考自 guavaokhttp,它们都使用了 jsr305 库。

方案二:guava | JDK 7

guavaJava 中最出色的工具库之一,所以 JDK 7 引进了很多 guava 中的概念。

这里只讨论 Preconditions 类,关于其他工具,请参考 guava 官方教程

使用示例:

Preconditions.checkNotNull(value) 方法细节:

这里为了方便理解,只展示了最简单的示例,实际上它就是对方法参数的 Null 值检测,由于提前检测比事后异常要准确得多,并且能够提供更精细的异常原因,因此推荐大家在类方法内部,添加类似的逻辑。

  • JDK 7 以上 API

使用时与 guava 中的 Preconditions.checkNotNull 没有差别,不过 guava 提供了更方便的重载方法,因此从 guava 的注释中,可以发现:

建议
  • 如果使用 guava 工具
    那么在方法参数检测时,使用 Preconditions 类;在字段状态检测时,使用 Verify 类。

  • 否则,在 JDK 7 及以上环境
    使用 jsr305Objects.requireNonNull 类,保证通用代码库工作正常,并且未来不会忘记调用规则。

总结

我的通用代码库是我自己做主,所以两种方案我都采取。

如果你开发的是小型项目,它需要足够纯粹的依赖环境,那么丢掉 jsr305 也是可以的;如果对依赖没有要求,偷偷把 guava 放进来也是极好的。

甚至通过学习 guava 官方教程,了解到很多潜在的代码威胁,你在开发项目时会更自信!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,170评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,138评论 25 709
  • 场景 在版本1.0时,弹出了一个通知栏此时,应用升级到2.0,再去点击这个通知栏会报错 原因分析RemoteVie...
    sofarsogoo_932d阅读 3,424评论 5 4
  • 由于我个人的三观,从珍珠很小的时候开始,我就和她灌输佛家的轮回观,包括人为什么出生,死后会去哪里等。所以,在珍珠的...
    米米姐姐阅读 289评论 1 1