Java 处理 Android Studio 的 NullPointerException lint 警告的正确方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23371938/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Proper way to handle Android Studio's NullPointerException lint warning
提问by Hackmodford
I'm new to android/java programming and am confused how to properly deal with this warning.
我是 android/java 编程的新手,对如何正确处理此警告感到困惑。
Method invocation '' may produce 'Java.lang.NullPointerException'
方法调用 '' 可能会产生 'Java.lang.NullPointerException'
Should I be ussing assert to remove the warning?
我应该使用 assert 来删除警告吗?
Or rather a runtime exception?
或者更确切地说是运行时异常?
Any help would be appreciated.
任何帮助,将不胜感激。
采纳答案by matiash
I doubt this question can be answered conclusively, as it's a matter of opinion. Or at least I believe so -- an opinion too. :)
我怀疑这个问题能否得到结论性的回答,因为这是一个见仁见智的问题。或者至少我相信——也是一种意见。:)
I understand you want "0 warnings" (a very laudable goal) but there's probably not a "one size fits all" issue. That said...
我知道您想要“0 警告”(一个非常值得称赞的目标),但可能没有“一刀切”的问题。那说...
Things I believe you should notdo:
事情,我相信你应该不会做的事:
- Use assert. While you can add an assert statement, Dalvik ignores them. You can configure an emulator to use them if you want, but not a real device (see Can I use assert on Android devices?). So while it would possibly remove the warning, it's useless in practice.
- Have the method throw
NullPointerException
. This would be a bad idea, generally. In this case, since you're probably overridingonOptionsItemSelected()
, it's not even possible.
- 使用断言。虽然您可以添加断言语句,但 Dalvik 会忽略它们。如果需要,您可以配置模拟器以使用它们,但不能配置为真实设备(请参阅我可以在 Android 设备上使用断言吗?)。因此,虽然它可能会消除警告,但在实践中是无用的。
- 有方法 throw
NullPointerException
。一般来说,这将是一个坏主意。在这种情况下,由于您可能覆盖了onOptionsItemSelected()
,因此甚至不可能。
Checking for (variable != null)
is generally the best approach. What to do if it is, though, presents some other options.
检查(variable != null)
通常是最好的方法。但是,如果是,该怎么办会提供一些其他选项。
- If it's a problem you can recoverfrom, i.e. you can continue the application even though the
searchView
isn't there, just do so. For example, just return from the method. It's a good idea to logthis situation though, so you can spot it while testing. - Otherwise, if continuing isn't possible, throw an exception. You want to fail early, so that the problem can be easily detected. A reasonable exception for this case would be IllegalStateException (see Java equivalent to .NET System.InvalidOperationException). It basically indicates that this method was executed at an inappropriate time. Be careful though, that as a
RuntimeException
, these exceptions are unchecked, and hence will probably cause the app to crash.
- 如果这是一个您可以从中恢复的问题,即即使
searchView
不存在,您也可以继续应用程序,只需这样做。例如,只需从方法返回。不过,记录这种情况是个好主意,这样您就可以在测试时发现它。 - 否则,如果无法继续,则抛出异常。您希望尽早失败,以便可以轻松检测到问题。这种情况下一个合理的例外是 IllegalStateException(参见Java 等价于 .NET System.InvalidOperationException)。它基本上表明此方法在不适当的时间执行。但是要小心,作为
RuntimeException
,这些异常是未经检查的,因此可能会导致应用程序崩溃。
回答by Emanuel S
Yes. Using if (Object != null){}
for validating is the proper way. try {} catch (NullPointerException) {}
is the next solution which is preferred in this case.
是的。使用if (Object != null){}
用于验证是正确的方式。try {} catch (NullPointerException) {}
是在这种情况下首选的下一个解决方案。
If you want to get ride of it, throw an NullPointerException
. Lint will ignore it in this case. public void myFunc() throws NullPointerException{}
.
如果你想搭上它,扔一个NullPointerException
. 在这种情况下,Lint 将忽略它。public void myFunc() throws NullPointerException{}
.
Anyway, good Coding always means validating everything for a possible problem while runtime. Validating != null
is just fine and should always be used whenever it's possible null.
无论如何,好的编码总是意味着在运行时验证所有可能的问题。验证!= null
很好,只要可能为空,就应该始终使用。
回答by Ryan
I like the answer to this link.
我喜欢这个链接的答案。
Warning is not an Error. And the warning which you are talking about says "it may produce", don't say 'it must produce'. So choice is yours. Either add null check or not
So, If you are sure that findViewById in your code will never be cause of NPE, then don't add the null check.
警告不是错误。您正在谈论的警告说“它可能会产生”,不要说“它必须产生”。所以选择权在你。要么添加空检查
因此,如果您确定代码中的 findViewById 永远不会成为 NPE 的原因,则不要添加空检查。
回答by Georgi Angelov
I personally prefer using try{ }catch{ } simply because it is more elegant. However, it does add a lot of bulk to your code, if you imagine putting every, possible, NULL value into a try catch (if they are not next to each other)
我个人更喜欢使用 try{ }catch{ } 只是因为它更优雅。但是,如果您想象将所有可能的 NULL 值放入 try catch 中(如果它们不相邻),它确实会为您的代码增加大量内容
回答by Herrbert74
I started to use
我开始使用
@SuppressWarnings("ConstantConditions")
@SuppressWarnings("ConstantConditions")
on simple methods where I'm sure that the id is not null.
在我确定 id 不为空的简单方法上。
回答by Iwo Banas
As @matiash pointed out there is no one-size-fits-all solution.
正如@matiash 指出的那样,没有一刀切的解决方案。
For me a good compromise was to disable NullPointerException
warning for all calls to findViewById()
and keep it for other method calls. That way I take responsibility for checking the resource ids but still get a benefit of getting warnings if I make other mistakes.
对我来说,一个很好的折衷方案是禁用NullPointerException
所有调用的警告,findViewById()
并为其他方法调用保留警告。这样我就负责检查资源 ID,但如果我犯了其他错误,仍然可以获得警告。
To achieve this I added _ -> !null
method contract with Android Studio quick fix menu.
为了实现这一点,我_ -> !null
在 Android Studio 快速修复菜单中添加了方法合同。
The action generated a following file file at android/support/v7/app/annotations.xml
in my project root.
该操作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>
Update:Unfortunately it doesn't survive Android Studio restarts :-( External annotations are really useful so I hope I'll figure out a way to make Android Studio load them after restart.
更新:不幸的是,它在 Android Studio 重启后无法生存:-( 外部注释非常有用,所以我希望我能找到一种方法让 Android Studio 在重启后加载它们。
回答by MatPag
What @Herrbert74 suggested it surely working fine, but sometimes it's better to not add a @SuppressWarnings("ConstantConditions")
to an entire method (if it's not trivial), a better approach could be to use //noinspection ConstantConditions
on the warned line.
@Herrbert74 建议它肯定可以正常工作,但有时最好不要将 a 添加@SuppressWarnings("ConstantConditions")
到整个方法中(如果它不是微不足道的),更好的方法可能是//noinspection ConstantConditions
在警告线上使用。
Those are my rules of thumb:
这些是我的经验法则:
Use
@SuppressWarnings("ConstantConditions")
when the method is simpleUse
//noinspection ConstantConditions
when the method is complex and you need to remove the warning only on a specific line
@SuppressWarnings("ConstantConditions")
方法简单时使用使用
//noinspection ConstantConditions
时,该方法是复杂的,你需要删除只在特定的行警告
回答by Mangesh
I've used Objects.requireNonNull()
which is a good way IMO. As @matiash mentioned, this is not a fool-proof way for every use case, but where you are sure that data won't be null
, you can use this approach to get rid of the warning. And if it does fail for some unknown reason, you will get NullPointerException
which you will get anyway without using this.
我使用过Objects.requireNonNull()
这是 IMO 的好方法。正如@matiash 所提到的,对于每个用例来说,这并不是一种万无一失的方法,但是如果您确定数据不会存在null
,您可以使用这种方法来消除警告。如果它确实由于某种未知原因而失败NullPointerException
,您将获得无论如何都不会使用它的结果。
// before
cal.setTime(date);
// after
cal.setTime(Objects.requireNonNull(date));