处理 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?)。因此,虽然它可能会删除警告,但在实践中它是无用的。 让方法 throw NullPointerException。一般来说,这将是一个坏主意。在这种情况下,由于您可能覆盖 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="&quot;_ -&gt; !null&quot;" />
    </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 基础控件飘红 处理办法

处理 Android Studio 的 NullPointerException lint 警告的正确方法

android studio升级3.0版本,问题处理

Android Studio TextView 文本选择处理程序图标位置

如何在android studio中处理最近的应用导航按钮?

无法处理文件 - Android Studio (app:mergeDebugResources)