Java 找出以编程方式抛出 NullPointerException 的变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2667908/
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
Find out what variable is throwing a NullPointerException programmatically
提问by Hectoret
I know I can find out if a variable is null in Java using these techniques:
我知道我可以使用以下技术找出 Java 中的变量是否为空:
- if
(var==null)
-> too much work try { ... } catch (NullPointerException e) { ...}
-> it tells me what line is throwing the exception- using the debugger -> by hand, too slow
- 如果
(var==null)
-> 工作太多 try { ... } catch (NullPointerException e) { ...}
-> 它告诉我哪一行抛出异常- 使用调试器 -> 手动,太慢了
Consider this line of code:
考虑这行代码:
if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0) {
I would like to know if there's a generic way to find out programatically what variable (not just the line) is throwing the NullPointerException in a certain area of code. In the example, knowing that
我想知道是否有一种通用的方法来以编程方式找出在特定代码区域中抛出 NullPointerException 的变量(不仅仅是行)。在示例中,知道
采纳答案by Asaph
Since it's possible to cause a null pointer exception without even involving a variable:
因为有可能在不涉及变量的情况下导致空指针异常:
throw new NullPointerException();
I would have to say that there is no generic way to pin down a null pointer exception to a specific variable.
我不得不说没有通用的方法来确定特定变量的空指针异常。
Your best bet would be to put as few as possible statements on each line so that it becomes obvious what caused the null pointer exception. Consider refactoring your code in the question to look something like this:
最好的办法是在每一行中放置尽可能少的语句,以便明确导致空指针异常的原因。考虑将问题中的代码重构为如下所示:
List items = this.superSL.items;
String name = items.get(name);
String source = name.getSource();
if (source.compareTo(VIsualShoppingList.Source_EXTRA) == 0) {
// ...
}
It's more lines of code to be sure. But it's also more readable and more maintainable.
需要确定的代码行数更多。但它也更具可读性和可维护性。
回答by Oren Hizkiya
I know you suggested that (var==null)
is too much work, but, as Miguel stated in the comments, that is what I would go with.
我知道你认为这(var==null)
工作量太大,但是,正如 Miguel 在评论中所说,这就是我会去的。
回答by Petar Minchev
What do you mean by "using the debugger -> by hand, too slow"? If your code is properly structured, then there won't be more than two or three variables used on the same line. Is it so slow to check them? You don't have NullPointers every minute.
“使用调试器-> 手动,太慢”是什么意思?如果您的代码结构正确,那么在同一行上使用的变量不会超过两三个。检查它们这么慢吗?你不是每分钟都有空指针。
回答by Bert F
Sorry, no, there is not a simple programmatic way to determine which variable or method call is the source of the exception. You could use something like Aspect-Oriented Programming (AOP), e.g. AspectJ, but this is not inherent to the language and is not generally incorporated into a program simply for debugging purposes.
抱歉,不,没有一种简单的编程方式来确定哪个变量或方法调用是异常的来源。您可以使用诸如Aspect-Oriented Programming (AOP) 之类的东西,例如AspectJ,但这不是语言固有的,并且通常不会仅仅为了调试目的而合并到程序中。
if (var==null) -> too much work
try { } catch() { }
Debugger
if (var==null) -> too much work
try { } catch() { }
Debugger
I know you don't want to hear this, but these are simply the cost of doing business.
我知道你不想听到这个,但这些只是做生意的成本。
if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0) {
It is unusual to see so many strung together method calls. I believe you best bet is to get in the habit of breaking these up more - not necessary down to 1 call per line, but fewer than this. Why?
看到这么多串在一起的方法调用是不寻常的。我相信你最好的办法是养成更多地分解这些的习惯 - 不必减少到每行 1 个电话,但少于这个。为什么?
1) Correctness
- is it valid in the design for one of these calls to return null? If so, you should break it out, test it, and handle it appropriately.
1) Correctness
- 在这些调用之一返回 null 的设计中是否有效?如果是这样,你应该打破它,测试它,并适当地处理它。
2) Understandability
- it would be easier for future maintainers (including future you) to understand if you intermediate, well-named variables to help clarify what is happening on this line.
2) Understandability
- 未来的维护者(包括未来的你)会更容易理解你是否中间的、命名良好的变量来帮助澄清这条线上发生的事情。
3) Efficiency
- usually when you go so deep into a graph (stringing together a series of method calls), its likely you will need to go back down around there later. Capturing this intermediate value in an intermediate variable means avoiding making one or more method calls again.
3) Efficiency
- 通常当你深入到一个图表中时(将一系列方法调用串在一起),你可能需要稍后再回到那里。在中间变量中捕获这个中间值意味着避免再次调用一个或多个方法。
4) Debugging
- as indicating by your question, spltiting a complex line like this up simplifies debugging. by narrowing down the possible source of the exception.
4) Debugging
- 正如你的问题所表明的,像这样拆分复杂的行可以简化调试。通过缩小异常的可能来源。
回答by Hardcoded
I think you should notice Demeters Law.
我想你应该注意德墨忒尔定律。
There aren't many people following it strictly, because it results in a lot of delegate methods.
But getting too far from it will result in dependencies on inner structures that should be transparent.
严格遵循它的人并不多,因为它导致了很多委托方法。
但是离它太远会导致对应该透明的内部结构的依赖。
回答by Konrad H?ffner
Unfortunately, Java will not show you the name of the variable or the exact position of an error other than the line number. If you use Eclipse you can use nullable annotations however, see http://www.fosslc.org/drupal/content/bye-bye-npefor example. See Which @NotNull Java annotation should I use?for other annotation systems.
不幸的是,除了行号之外,Java 不会向您显示变量的名称或错误的确切位置。但是,如果您使用 Eclipse,则可以使用可为空的注释,例如,请参见http://www.fosslc.org/drupal/content/bye-bye-npe。请参阅我应该使用哪个 @NotNull Java 注释?对于其他注释系统。
回答by Egis
What has worked really beautifully to me is catching the exception where it normally gets thrown and then using Log to see whether any of them have 'null' values.
对我来说真正有效的是捕获通常抛出的异常,然后使用 Log 查看它们中是否有任何一个具有“空”值。
My code:
我的代码:
try {
if (description_visible) advice_title_cur.setText(all_title_array[pos]);
else advice_title_cur.setText(all_title_array[pos] + "...");
} catch (NullPointerException e) {
e.printStackTrace();
Log.e("My name", "description_visible " + description_visible);
Log.e("My name", "advice_title_cur " + advice_title_cur);
Log.e("My name", "all_title_array " + all_title_array);
Log.e("My name", "pos " + pos);
}
回答by VonC
You might consider, as announced here, the JDK 14 which should include the JEP 358:
您可能会考虑,正如这里所宣布的,JDK 14 应该包含JEP 358:
JEP 358: Helpful NullPointerExceptions
Suppose an NPE occurs in this code:
a.b.c.i = 99;
The filename and line number do not pinpoint exactly which variable was null.
Was ita
orb
orc
?A similar problem occurs with array access and assignment. Suppose an NPE occurs in this code:
a[i][j][k] = 99;
The filename and line number do not pinpoint exactly which array component was null.
Was ita
ora[i]
ora[i][j]
?Description:
If the more complex statement
a.b.c.i = 99;
throws an NPE, the message would dissect the statement and pinpoint the cause by showing the full access path which led up to the null:
JEP 358:有用的 NullPointerExceptions
假设在这段代码中出现了一个 NPE:
a.b.c.i = 99;
文件名和行号不能准确指出哪个变量为空。
是不是a
还是b
和c
?数组访问和分配也会出现类似的问题。假设在这段代码中出现了一个 NPE:
a[i][j][k] = 99;
文件名和行号不能准确指出哪个数组组件为空。
是不是a
还是a[i]
和a[i][j]
?描述:
如果更复杂的语句
a.b.c.i = 99;
抛出 NPE,消息将剖析该语句并通过显示导致空值的完整访问路径来查明原因:
Exception in thread "main" java.lang.NullPointerException:
Cannot read field "c" because "a.b" is null
at Prog.main(Prog.java:5)
Again: to be tested with JDK 14.
再次:使用 JDK 14 进行测试。
Holgeradds in the comments:
For the expression
a[i][j][k]
, there's also the possibility that either,i
,j
, ork
has typeInteger
and is null, so unboxing fails.In real life scenarios, the expression to the right of the
=
might bear potential for NPE too.I tried with jdk-14.0.1
it works; it produces a message like
Cannot invoke "java.lang.Integer.intValue()" because "i" is null then.
When the method has been compiled without debug information, it will use something like "
<local8>
" instead of "i
", but that's unavoidable.
对于 expression
a[i][j][k]
,也有可能i
,j
, 或k
具有类型Integer
并且为空,因此拆箱失败。在现实生活场景中,右边的表达
=
也可能具有 NPE 的潜力。我试过 jdk-14.0.1
有用; 它产生一条消息,如
Cannot invoke "java.lang.Integer.intValue()" because "i" is null then.
当方法在没有调试信息的情况下被编译时,它会使用类似“
<local8>
”的东西而不是“i
”,但这是不可避免的。