处理 Android Studio 的 NullPointerException lint 警告的正确方法
Posted
技术标签:
【中文标题】处理 Android Studio 的 NullPointerException lint 警告的正确方法【英文标题】:Proper way to handle Android Studio's NullPointerException lint warning 【发布时间】:2014-06-15 19:41:32 【问题描述】:我是 android/java 编程新手,很困惑如何正确处理此警告。
方法调用''可能会产生'Java.lang.NullPointerException'
我应该使用 assert 来删除警告吗?
或者更确切地说是运行时异常?
任何帮助将不胜感激。
【问题讨论】:
如果您首先在对象上检查 null,警告就会消失。尽管如果您确定某些内容永远不会为空,那么您最终会进行大量不必要的空检查 我应该禁用这个 lint 警告吗? 我不会,因为它可能会为您可能忽略的事情带来光明,但我个人只是在我知道某些事情不会真正为空时忽略它 我在警告方面遇到了 ocd 问题:P 【参考方案1】:我使用了Objects.requireNonNull()
,这是 IMO 的好方法。正如@matiash 所提到的,这不是每个用例的万无一失的方法,但是如果您确定数据不会是null
,您可以使用这种方法来消除警告。如果由于某种未知原因它确实失败了,你会得到NullPointerException
,无论如何你都会得到它,而无需使用它。
// before
cal.setTime(date);
// after
cal.setTime(Objects.requireNonNull(date));
【讨论】:
【参考方案2】:我怀疑这个问题能否得到最终回答,因为这是一个见仁见智的问题。或者至少我是这样认为的——也是一种观点。 :)
我知道您想要“0 个警告”(一个非常值得称赞的目标),但可能没有“一刀切”的问题。那就是……
我认为你应该不做的事情:
使用断言。虽然您可以添加断言语句,但 Dalvik 会忽略它们。如果你愿意,你可以配置一个模拟器来使用它们,但不是一个真实的设备(见Can I use assert on Android devices?)。因此,虽然它可能会删除警告,但在实践中它是无用的。 让方法 throwNullPointerException
。一般来说,这将是一个坏主意。在这种情况下,由于您可能覆盖 onOptionsItemSelected()
,这甚至是不可能的。
检查(variable != null)
通常是最好的方法。但是,如果是,该怎么办,提供了一些其他选择。
searchView
不存在,您也可以继续应用程序,只要这样做。例如,只需从方法返回。不过,最好记录这种情况,这样您就可以在测试时发现它。
否则,如果无法继续,则抛出异常。你想fail early,这样就可以很容易的发现问题。这种情况的一个合理例外是 IllegalStateException(请参阅Java equivalent to .NET System.InvalidOperationException)。它基本上表明该方法是在不适当的时间执行的。但请注意,作为RuntimeException
,这些异常是未经检查的,因此可能会导致应用崩溃。
【讨论】:
您自己的链接答案表明可以在真实设备上启用 assert 关键字(尽管显然只能通过 ADB)。 @TomG AFAIK setprop 只能在有根设备上使用。但也许我错了? 哦,你可能是对的——我自己只在有根信息亭风格的设备上使用过它。没关系! 这些警告中的绝大多数都发生在 findViewById() 调用之后,这可能会发生很多!作为 android 程序员,我们习惯了来自这些的空指针错误,并在对布局文件进行更改时使用它们进行调试。必须测试这些调用中的每一个都非常令人头疼。这个新的“功能”(旧版本的 Android Studio 没有这个警告)大大增加了代码膨胀。 @ScottBiggs 幸运的是,您现在可以禁用某些方法的警告。请参阅下面的答案。【参考方案3】:@Herrbert74 建议它确实可以正常工作,但有时最好不要在整个方法中添加 @SuppressWarnings("ConstantConditions")
(如果它不是微不足道的),更好的方法可能是在警告行上使用 //noinspection ConstantConditions
。
这些是我的经验法则:
方法简单时使用
@SuppressWarnings("ConstantConditions")
当方法复杂并且只需要删除特定行上的警告时使用
//noinspection ConstantConditions
【讨论】:
非常优雅的解决方案。 +1 我个人意见//noinspection ConstantConditions 更好。【参考方案4】:是的。使用if (Object != null)
进行验证是正确的方法。 try catch (NullPointerException)
是在这种情况下首选的下一个解决方案。
如果您想搭便车,请发送NullPointerException
。在这种情况下,Lint 将忽略它。 public void myFunc() throws NullPointerException
.
无论如何,好的编码总是意味着在运行时验证所有可能出现的问题。验证!= null
很好,只要可能为空,就应该始终使用它。
【讨论】:
【参考方案5】:正如@matiash 指出的那样,没有万能的解决方案。
对我来说,一个很好的折衷方案是对所有对findViewById()
的调用禁用NullPointerException
警告,并为其他方法调用保留它。这样,我负责检查资源 ID,但如果我犯了其他错误,仍然可以获得警告。
为了实现这一点,我在 Android Studio 快速修复菜单中添加了 _ -> !null
方法契约。
该操作在我的项目根目录中的android/support/v7/app/annotations.xml
处生成了以下文件文件。
<root>
<item name='android.support.v7.app.AppCompatActivity android.view.View findViewById(int)'>
<annotation name='org.jetbrains.annotations.Contract'>
<val val=""_ -> !null"" />
</annotation>
</item>
</root>
更新: 不幸的是,它无法在 Android Studio 重新启动 :-( 外部注释真的很有用,所以我希望我能找到一种方法让 Android Studio 在重启后加载它们。
【讨论】:
【参考方案6】:我开始用了
@SuppressWarnings("ConstantConditions")
关于我确定 id 不为空的简单方法。
【讨论】:
完美,这就是我们想要的。仅对我们确定 id 不能为 null 的方法禁用检查。 或者在你想要空指针错误的地方使用它(比如onCreate
)。【参考方案7】:
我个人更喜欢使用 try catch ,因为它更优雅。但是,如果您想将每个可能的 NULL 值放入 try catch 中(如果它们不相邻),它确实会为您的代码增加很多体积
【讨论】:
【参考方案8】:我喜欢这个link 的答案。
警告不是错误。还有你所说的警告 说“它可能生产”,不要说“它必须生产”。所以选择是 你的。是否添加空检查
所以,如果您确定代码中的 findViewById 永远不会导致 NPE,那么就不要加空检查了。
【讨论】:
以上是关于处理 Android Studio 的 NullPointerException lint 警告的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
处理 Android Studio 的 NullPointerException lint 警告的正确方法
Android Studio TextView 文本选择处理程序图标位置