Android @NonNull的用处
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android @NonNull的用处相关的知识,希望对你有一定的参考价值。
经过一些阅读和问题like this one我想知道是否有一点使用@NonNull
android支持注释。
如果我尝试使用注释为@NonNull的null参数调用方法,我可以看到来自Android Studio的非常小的警告。只是警告??
单元测试怎么样?我应该用null参数测试方法吗?如果我这样做...我会得到一个NullPointerException
,我的测试将失败。
假设我们是两位开发人员。一个在API上工作,另一个在各种方式下测试API。作为第二个开发人员,我有责任测试所有内容,以便API具有防弹功能。这是单元测试的重点,对吗?
那么......第一个使用@NonNull的开发人员有什么意义呢?
如果其他人将此API与null参数一起使用......那么API将抛出NPE。然后他会想:“Urg,那个API糟透了...... NPE!”他会是对的。那个顽皮的开发人员没有检查他发送的参数是否为null应该面临一个IllegalArgumentException,因为这是他的错误而不是API的错误!
我错了吗 ?
我认为这些注释会强制编译器显示像attempting to call methodName(@NonNull Object object) with null parameter
这样的错误。
更新1
好的,谢谢大家的意见。如果可能的话,我想总结一下我在这里遇到的“问题”。以抽象的方式。
我编写了一些代码(一个API,一个库,一个类,等等),私有内部代码由提供功能的公共方法包装。
假设这些公共方法将被其他任何人(包括我)使用。他们中的一些人接受的参数必须永远不会为空,否则一切都会破裂。
阅读您的评论,我面临以下选择:
- 继续使用Java文档支持的合同/注释(
@NonNull
),规定parameter must not be null
。不要检查空参数(否则IDE会警告我),不知何故,祈祷我永远不会收到空参数; - 与上面相同,但强制执行空检查(即使IDE将警告
condition will always be false
)并抛出IllegalArgumentException
而不是在我收到空参数的情况下导致NPE; - 停止使用合同/注释,使用Java Doc警告其他开发人员并添加所有参数的手动检查。
最后,对于单元测试......我知道我不能使用防弹代码,但我喜欢尽可能地“测试”我的代码,以防止我的代码出现意外行为以及验证过程(这是在单元测试的基础上,我相信) -
它的主要目的是为您的同事提供信息。一个人永远不是大型项目的唯一程序员。使用NotNull告诉其他程序员,函数的契约意味着你永远不能向它发送null,所以他们不这样做。否则,我可能会假设调用setFoo(null)将清除Foo,而API无法处理没有Foo。
在我看来,您的#2方法是为API /库执行此操作的正确方法。使用注释进行静态分析以防止编译时尝试使用null调用该方法,并在运行时使用空检查以提供有用的异常(并且如果为null则快速失败/防止代码中发生意外事件)对象被传入。在null检查之前使用// noinspection ConstantConditions指令告诉IDE禁止警告(因为您检查null是否有正当理由)。
随机NPE表示库/ api作者可能遗漏了某些内容并且有一个未在其代码中处理的错误。
IllegalArgumentException(或带有问题描述的NPE - 在此实例中使用的异常是基于意见的参数)表示调用者在调用方法时出错。
但最终,在您已经使用@NonNull注释后是否测试null将是基于意见和依赖于情境的。
评论可能为时已晚,但比以后更好:)
有一个Traute javac插件,它根据方法参数的注释将空值检查插入到生成的字节码中。
这是一个sample Android project,说明了这一点。
以上是关于Android @NonNull的用处的主要内容,如果未能解决你的问题,请参考以下文章
错误记录Android Studio 编译时 Kotlin 代码编译报错 ( 升级支持库时处理 @NonNull 参数 )
Android Studio错误的含义:未注释的参数会覆盖@NonNull参数
[Android ViewModel] public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory 问题
程序包androidx.support.annotation不存在/import android.support.annotation.NonNull;报错