Java 什么时候可以捕获 NullPointerException?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18265940/
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
When is it OK to catch NullPointerException?
提问by 500004dolkong
Effective java recommends that we shouldn't catch
NullPointerException
.
Is it always right?
有效的 java 建议我们不应该catch
NullPointerException
. 它总是正确的吗?
In many cases of catching NullPointerException
, catch body only calls printStackTrace()
.
在很多情况下NullPointerException
,catch body 只调用printStackTrace()
。
If I don't catch NullPointerException
and call printStackTrace()
, how I can check the place where the exception
occurred?
如果我不赶上NullPointerException
并打电话printStackTrace()
,我怎么能检查exception
发生的地方?
And also if I catch NullPointerException
and the catch
body is empty, we cannot get any stack information at that time, can we?
而且如果我抓住NullPointerException
并且catch
主体是空的,那么我们当时无法获得任何堆栈信息,可以吗?
UPDATE
更新
I analyzed statistics of catching RuntimeException in google android source, AOSP4.2.2_r1.2.
我分析了google android源码AOSP4.2.2_r1.2中捕获RuntimeException的统计数据。
There are 249 RuntimeException catchings and followings are statistics of catch-body.
有 249 个 RuntimeException 捕获,以下是捕获体的统计信息。
42%: throw it again as other Exceptions (RuntimeException: 33%, others: 8%)
32%: just return null or 0/false/true or other default values
14%: just call log or printstacktrace
5%: just comment like "// Fall through.", "// ignore, not a valid type.", "// system process dead", "// do nothing"
2%: empty body
3%: display error messages or send fail codes (ex. network service discovery failed: replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, NsdManager.FAILURE_INTERNAL_ERROR); )
3%: intialize or reset related variables.
In almost cases, dalvik and external handle NPE by throwing other Exceptions.
在几乎情况下,dalvik 和外部通过抛出其他异常来处理 NPE。
But frameworks usually handle by returning null or other values.
但是框架通常通过返回 null 或其他值来处理。
Do you think that throwing other Exceptions in catch-body is not bad or good handling?
If NPE occured in higher levels(ex. applications) and the developer confirms the exception is not critical because the app is fully independent, can I accept for our developer to ignore the NPE by catching?
你认为在 catch-body 中抛出其他 Exceptions 是不是不好或好处理?
如果 NPE 发生在更高级别(例如应用程序)并且开发人员确认异常并不重要,因为应用程序是完全独立的,我是否可以接受我们的开发人员通过捕获来忽略 NPE?
and one more thing,
还有一件事情,
Can I conclude that google android framework source code may be some unstable in aspects of RuntimeException
?
我可以断定 google android 框架源代码在某些方面可能有些不稳定RuntimeException
吗?
采纳答案by Stephen C
Effective java recommend that we shouldn't catch NullPointerException. Is it always right?
有效的 java 建议我们不应该捕获 NullPointerException。它总是正确的吗?
In nearly all cases it is correct.
在几乎所有情况下,它都是正确的。
NullPointerException
is usually a result of a bug; i.e. your application encountered a null
object reference in a situation where it was not anticipated, and then attempted to use it. In this scenario, since you (the programmer) did not anticipate the null
, it is next to impossible to know whether it is safe to attemptto recover, and / or to know what "remediation" might be required. So the best thing to do is to let the NPE propagate to the base level, and then treat it as a generic bug. (In "network service" applications, it may be appropriate to return a "service error" response, and attempt to continue.)
NullPointerException
通常是错误的结果;即,您的应用程序null
在未预料到的情况下遇到了对象引用,然后尝试使用它。在这种情况下,由于您(程序员)没有预料到null
,因此几乎不可能知道尝试恢复是否安全,和/或知道可能需要什么“补救”。所以最好的办法是让 NPE 传播到基础级别,然后将其视为通用错误。(在“网络服务”应用程序中,返回“服务错误”响应并尝试继续操作可能是合适的。)
The other scenario is where you (the programmer) anticipate that a null
might be delivered. In this case, the best strategy is (nearly always) to explicitly test for the null
beforeyou attempt to use it, thereby avoidingthe NPE ... and the need to handle it. There are two reasons for this:
另一种情况是您(程序员)预计null
可能会交付 a。在这种情况下,最好的策略是(几乎总是)null
在您尝试使用它之前明确测试它,从而避免NPE ... 以及处理它的需要。有两个原因:
Exception handling is typically expensive. Indeed it can be many orders of magnitudemore expensive than testing for a
null
.If you allow the expected NPE to happen and then catch it, you are liable to also catch other unexpectedNPEs ... and handle them incorrectly.
异常处理通常很昂贵。事实上,它可以是多个数量级的比对测试更昂贵
null
。如果您允许预期的 NPE 发生然后捕获它,那么您也可能会捕获其他意外的NPE ......并错误地处理它们。
Note that I qualified the above by saying "nearly always". It is theoretically possible to have a scenario where explicit tests for null
clutter up your code so much that it is at least worth consideringallowing the NPE to happen. However, there is still the possibility of unexpected NPEs as well ... depending on the code. So this approach is always potentiallyfragile.
请注意,我通过说“几乎总是”来限定上述内容。理论上可能会出现这样一种场景,其中显式测试使null
您的代码变得如此混乱,以至于至少值得考虑允许 NPE 发生。但是,仍然存在意外 NPE 的可能性......取决于代码。所以这种方法总是潜在的脆弱。
(FWIW - I've never encountered a real case where this would be a good idea ...)
(FWIW - 我从来没有遇到过这样一个好主意的真实案例......)
In many cases of catching NullPointerException, catch body only calls printStackTrace().
在很多捕捉 NullPointerException 的情况下,catch body 只调用了 printStackTrace()。
That is probably bad code. Doing nothing is rarely the correct way to recover from an NPE.
那可能是糟糕的代码。什么都不做很少是从 NPE 中恢复的正确方法。
If I don't catch NullPointerException and call printStackTrace(), how I can check the place where the exception occurred?
如果我没有捕获 NullPointerException 并调用 printStackTrace(),我如何检查发生异常的位置?
You let the NPE propagate to the base level. There you catch and print (or log) a stacktrace for allunhandled exceptions, and then either bail out or attempt to recover ... if that is feasible.
您让 NPE 传播到基本级别。在那里您可以捕获并打印(或记录)所有未处理异常的堆栈跟踪,然后退出或尝试恢复……如果可行的话。
And also if I catch NullPointerException and the catch body is empty, we cannot get any stack information at that time, can we?
而且,如果我捕获 NullPointerException 并且捕获主体为空,那么我们此时无法获取任何堆栈信息,是吗?
Never, ever do this! It is called "squashing" and is dangerous. (Especially since, as I explained above, the NPE may be due to something that you / your code did not anticipate.)
永远,永远不要这样做!它被称为“挤压”并且是危险的。(特别是因为,正如我上面所解释的,NPE 可能是由于您/您的代码没有预料到的事情。)
And no, if you do this, you can't get the stack trace. It is gone.
不,如果你这样做,你就无法获得堆栈跟踪。它不见了。
FOLLOWUP
跟进
I don't place much trust / faith on some general strategies for "avoiding NPEs"1. For instance stuff like this:
我对“避免 NPE” 1 的一些一般策略不太信任。例如这样的东西:
return (someObject != null) ? someObject.toString() : "";
always make me suspicious that the programmer is not thinking about the problem. Why was someObject
a null
in the first place?
总是让我怀疑程序员没有考虑问题。为什么首先是someObject
a null
?
A NPE is caused by having a null
in place where you don't expect it. As such, NPEs are usually symptomsof a problem rather than the actual problem itself. To my mind, NPEs are not something to be avoided. Rather, you should be using the NPEs to find and fix the root causeof the unexpected null
. Code like the above that avoids the NPE gets in the way of that goal.
NPE 是由null
您不期望的地方引起的。因此,NPE 通常是问题的征兆,而不是实际问题本身。在我看来,NPE 不是可以避免的。相反,你应该使用在NPE来查找和解决根源意想不到的null
。像上面这样的代码可以避免 NPE 妨碍实现该目标。
So I prefer / recommend strategies for avoiding null
values in unexpected places.
所以我更喜欢/推荐null
在意想不到的地方避免值的策略。
Make sure that every reference field is gets initialized to a non-null value ... unless
null
is a meaningfulvalue.Try to avoid having
null
as a meaningful value, especially if there is an alternative. For instance, an empty String, a zero length array, an empty collection, a distinguished instance that means "undefined" or whatever. Or, for Java 8 and later, useOptional
.Don't return
null
as an error or an indication of a special case. (Throw an exception or return a distinguished value.)Check early for unanticipated
null
values (e.g.null
arguments), and throw the NPE sooner rather than later.In the few places where a
null
argument or result is legitimate, make sure that your javadocs document this clearly and explicitly. If there is no documentation, then the implication should be thatnull
is not allowed and won't be returned.
确保每个引用字段都被初始化为非空值......除非
null
是一个有意义的值。尽量避免具有
null
有意义的值,尤其是在有替代方案的情况下。例如,一个空字符串、一个零长度数组、一个空集合、一个表示“未定义”的特殊实例等等。或者,对于 Java 8 及更高版本,使用Optional
.不要
null
作为错误或特殊情况的指示返回。(抛出异常或返回一个可分辨的值。)尽早检查意外
null
值(例如null
参数),并尽早抛出 NPE 。在
null
参数或结果合法的少数地方,请确保您的 javadoc 清楚明确地记录了这一点。如果没有文件,则暗示应该null
是不允许的并且不会返回。
And wherever you get an NPE, make sure that you find and fix the realsource of the problem ... not just the specific statement that threw the exception.
无论您在何处获得 NPE,都要确保找到并修复问题的真正根源……而不仅仅是引发异常的特定语句。
1 - There is value in knowing about places in the standard Java APIs where null
is used (or abused) as a return value. For instance, Class.getResourceAsStream(...)
or HttpRequest.getParam(...)
. Those "advice for avoiding NPE" documents are useful in as much that they point out these traps.
1 - 了解标准 Java API 中null
用作(或滥用)作为返回值的位置是有价值的。例如,Class.getResourceAsStream(...)
或HttpRequest.getParam(...)
。那些“避免 NPE 的建议”文档非常有用,因为它们指出了这些陷阱。
回答by anshulkatta
You dont have to actually do e.printstacktrace()
all the time , you can specify your own body message using logger or System.out.println()
您实际上不必一直这样做e.printstacktrace()
,您可以使用 logger 或System.out.println()
回答by Ruchira Gayan Ranaweera
NullPointerException
typically occurs due to logical errors in our code. We can eliminate NullPointerException
by avoiding unsafe operations. If any NullPointerException
still happens, you can see it in StackTrace
.
NullPointerException
通常由于我们代码中的逻辑错误而发生。我们可以NullPointerException
通过避免不安全的操作来消除。如果NullPointerException
仍然发生任何情况,您可以在StackTrace
.
For example
例如
if (Obj.getName("Sam")) {
// only executes if Obj != null
}
We can avoid NullPointerException
as follows
我们可以避免NullPointerException
如下
if (Obj == null){
System.out.println("Null Obj, Can't proceed");
} else {
Obj.getName("Sam")
}
回答by Maxim Efimov
You definetly should not use empty catch block without REALLY IMPORTANTreason. Usually there is no such reason.
没有真正重要的原因,你绝对不应该使用空的 catch 块。通常没有这样的原因。
Usually it's good either to check if variable is null or catch NPE and trow more appropriate reason. For example if a method getCar()
returned null
you may catch NPE on trying to call some method of the car
, or check if the car is null
and throw RuntimeException
(but only if the situation is really exceptionable). Thus you make errors more abstract-binded and easier to understand.
通常最好检查变量是否为空或捕获 NPE 并找出更合适的原因。例如,如果getCar()
返回了一个方法,null
您可能会在尝试调用 的某些方法时捕获 NPE car
,或者检查汽车是否存在null
并抛出RuntimeException
(但前提是情况确实异常)。因此,您可以使错误更加抽象且易于理解。
回答by Jayesh
Generally It is recommend that one should not catch NullPointerException
and let it be handled by JVM.
一般建议不要捕获NullPointerException
,让JVM处理。
But it all depends,
Say for eg: if you have code like List<Student> listStudent = getAllStudent();
但这一切都取决于,比如说:如果你有这样的代码 List<Student> listStudent = getAllStudent();
here getAllStudent()
connects to DB and give you result, Here before doing any operation on list object you should check that
这里getAllStudent()
连接到数据库并给你结果,在对列表对象进行任何操作之前,你应该检查一下
if(listStudent != null){
//do the task.
}else{
//Show Message like no student is there instead of catching NullPointerException
}
if you will not do, then chances are there that NullPointerException
can occur if no data is there.
如果您不这样做,那么NullPointerException
如果没有数据,则可能会发生这种情况。
so better practice is to check for Nulls but not handle it like
所以更好的做法是检查 Nulls 但不要像这样处理它
try{
}catch(NullPointerException e){
}
回答by rocketboy
When an exception is thrown, be it any exception, jvm looks for the closest handler
(catch block). If it is not found in the current method, it looks for the handler in the calling code and so on. SO basically the entire calling stack
is searched bottom-up to look for a catch block which can handle the said exception. If no handler is found jvm uses the default handler which calls the e.printStackTrace()
当抛出异常时,无论是任何异常,jvm 都会寻找最近的handler
(catch 块)。如果在当前方法中没有找到它,它会在调用代码中寻找处理程序等等。所以基本上整个calling stack
搜索都是自下而上的,以寻找可以处理所述异常的 catch 块。如果没有找到处理程序,jvm 使用默认处理程序调用e.printStackTrace()
Now NullPointerException
is a runtime exception, which basically points to some logical fallacy in the code. There are times when you may
want to catch it. But as a thumbrule:
现在NullPointerException
是一个运行时异常,它基本上指向代码中的一些逻辑谬误。有时您may
想抓住它。但作为一个拇指规则:
- don't catch runtime exceptions, they generally point to logical errors
- don't leave an empty catch block, you will lose the stacktrace and the exception if you catch it but do not act upon it.
- don't just print the stacktrace to standard outout, instead log it somewhere for later analysis, if needed
- 不捕获运行时异常,它们通常指向逻辑错误
- 不要留下空的 catch 块,如果您捕获它但不对其采取行动,您将丢失堆栈跟踪和异常。
- 如果需要,不要只是将堆栈跟踪打印到标准输出,而是将其记录在某处以供以后分析
回答by Makoto
The convention is to avoid catching any sort of runtime exception. The reason being: something horriblehas gone wrong, and you as a developer should be keen on fixing it thirty minutes ago.
约定是避免捕获任何类型的运行时异常。原因是:出现了可怕的错误,作为开发人员的您应该在 30 分钟前热心修复它。
NullPointerException
is, in fact, a subclass of RuntimeException
. Like other classes that have a parent of RuntimeException
, they are considered unchecked- so code compiles even if it's going to produce an NPE:
NullPointerException
实际上是 的一个子类RuntimeException
。与其他具有 父级的类一样RuntimeException
,它们被认为是未经检查的- 因此即使代码将生成 NPE,也会编译:
// This would appropriately return "false", if the order were reversed
// and something was empty.
public boolean doSomething(String something) {
String hello = null;
if(hello.equals(something)) {
System.out.println("Wow");
}
}
Explicitlycatching any sort of runtime exception indicates that you expect horrible, bad things to happen over the course of the program, and you wish to gloss over that fact.
显式捕获任何类型的运行时异常表明您预计在程序运行过程中会发生可怕的、糟糕的事情,并且您希望掩盖这一事实。
As for what goes in the body of the catch
block...that's probably being automatically generated by your IDE. If you're not propagating the exception to the higher levels of your application, then you need to get useful context as to why your program blew up.
至于catch
块体中的内容……这可能是由您的 IDE 自动生成的。如果您没有将异常传播到应用程序的更高级别,那么您需要获得有用的上下文,了解您的程序为什么会爆炸。
If you don't put anything in the catch block, it's silently ignored - which is bad.
如果你没有在 catch 块中放入任何东西,它就会被默默地忽略——这是不好的。
回答by java_enthu
Usually NullPointerException
signifies a logical error in the API usage or exepcted value is missing. That's why it's recommended to to throw it back. However you can catch it. Practically
通常NullPointerException
表示 API 使用中存在逻辑错误或缺少预期值。这就是为什么建议把它扔回去的原因。但是你可以抓住它。几乎
I will suggest you to catch when you want to give default values for the passed null parameters.
当您想为传递的空参数提供默认值时,我会建议您抓住。
For example :
例如 :
You are expecting timeout value to be configurable and you expect that user has to pass it. However user forgets to pass it. In this scenario you can catch the NPE and log a warning that you are using the default value for the parameter.
您希望超时值是可配置的,并且您希望用户必须通过它。但是用户忘记传递它。在这种情况下,您可以捕获 NPE 并记录您正在使用参数默认值的警告。
回答by Ankur Lathi
NullPointerException
is a situation in code where you try to access/ modify an object which has not been initialized yet.
NullPointerException
是代码中的一种情况,您尝试访问/修改尚未初始化的对象。
It essentially means that object reference variable is not pointing anywhere and refers to nothing or ‘null'.
它本质上意味着对象引用变量没有指向任何地方,并且不引用任何内容或“空”。
Joshua blochin effective java
says that:
约书亚布洛赫在effective java
说:
“Arguably, all erroneous method invocations boil down to an illegal argument or illegal state, but other exceptions are standardly used for certain kinds of illegal arguments and states. If a caller passes null in some parameter for which null values are prohibited, convention dictates that NullPointerException be thrown rather than IllegalArgumentException.”
“可以说,所有错误的方法调用都归结为非法参数或非法状态,但其他例外通常用于某些类型的非法参数和状态。如果调用者在某些禁止为 null 值的参数中传递 null,则约定规定抛出 NullPointerException 而不是 IllegalArgumentException。”
So, if you must allow NullPointerException
in some places in you code then make sure you make them more informative then they usually are.
因此,如果您必须NullPointerException
在代码中的某些地方允许,那么请确保您使它们比通常情况下提供更多信息。
Read more about Effective NPE Handling from here:
从此处阅读有关有效 NPE 处理的更多信息:
回答by Andyz Smith
Robust, user centric code should try to catch such a 'FATAL ERROR' if there is anything ANYTHING at all you could do about it. You could retry the attempted function call. Perhaps this null exception is due to something transient. Something that really shouldn't throw an exception and should be coded better for the transient failure but, which, however should not deter the end user from getting what he wants, instead of abandoning what could be a lengthy stateful form input process, and only on the last, completely insignificant step, like entering the users's email preference or something does the null pointer error occur and trash the user's existing input.
如果您可以做任何事情,那么健壮的、以用户为中心的代码应该尝试捕获这样的“致命错误”。您可以重试尝试的函数调用。也许这个空异常是由于一些暂时的。确实不应该抛出异常并且应该为瞬态故障更好地编码的东西,但是,这不应阻止最终用户获得他想要的东西,而不是放弃可能是冗长的有状态表单输入过程,并且只在最后一个完全无关紧要的步骤中,例如输入用户的电子邮件首选项或发生空指针错误并破坏用户现有输入的内容。