Java 找出以编程方式引发NullPointerException的变量

Java 找出以编程方式引发NullPointerException的变量,java,debugging,nullpointerexception,Java,Debugging,Nullpointerexception,我知道我可以使用以下技术确定Java中的变量是否为null: 如果(var==null)->工作量过大 try{…}catch(NullPointerException e){…}->它告诉我哪行抛出异常 手动使用调试器->太慢 考虑这一行代码: if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0) { 我想知道是否有一种通用的方法可以通过编程找出在特定代码区

我知道我可以使用以下技术确定Java中的变量是否为null:

  • 如果
    (var==null)
    ->工作量过大
  • try{…}catch(NullPointerException e){…}
    ->它告诉我哪行抛出异常
  • 手动使用调试器->太慢
考虑这一行代码:

if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0)  {

我想知道是否有一种通用的方法可以通过编程找出在特定代码区域中抛出NullPointerException的变量(不仅仅是行)。在本例中,知道

我知道您建议
(var==null)
的工作量太大,但是,正如Miguel在评论中所说的,这就是我要做的。

因为即使不涉及变量也可能导致空指针异常:

throw new NullPointerException();
我不得不说,没有通用的方法将空指针异常固定到特定变量

最好的办法是在每一行上放尽可能少的语句,这样就可以清楚地知道是什么导致了空指针异常。考虑重构问题中的代码,以寻找类似的情况:

List items = this.superSL.items;
String name = items.get(name);
String source = name.getSource();
if (source.compareTo(VIsualShoppingList.Source_EXTRA) == 0)  {
    // ...
}

可以肯定的是,这需要更多的代码行。但是它也更具可读性和可维护性。

你所说的“使用调试器->手动,速度太慢”是什么意思?如果代码结构正确,那么在同一行中使用的变量不会超过两个或三个。检查它们这么慢吗?您并不是每分钟都有空指针。

对不起,没有,没有一种简单的编程方法来确定哪个变量或方法调用是异常的来源。您可以使用类似的东西,例如,但这不是该语言固有的,通常不会仅仅为了调试目的而合并到程序中

  • if(var==null)->工作量过大
  • 试试{}catch(){}
  • 调试器
我知道你不想听这些,但这些只是做生意的成本

if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0)  {
看到如此多的方法调用串在一起是不寻常的。我相信你最好的办法是养成更多地打破这些习惯——不必每行打一个电话,但要比这少。为什么?

1)
正确性
-在设计中,其中一个调用返回null是否有效?如果是这样的话,你应该打破它,测试它,并妥善处理它

2)
可理解性
-如果您使用中间的、命名良好的变量来帮助澄清这条线路上发生的事情,未来的维护人员(包括未来的您)将更容易理解

3)
效率
-通常,当您深入到图形中(将一系列方法调用串联在一起)时,您可能需要稍后再回到图形中。在中间变量中捕获这个中间值意味着避免再次进行一个或多个方法调用

4)
调试
-如您的问题所示,将这样一条复杂的行添加到上面可以简化调试。通过缩小异常的可能来源。

我认为您应该注意到

没有多少人严格遵循它,因为它会产生很多委托方法。

但是,如果离它太远,就会导致对内部结构的依赖,而内部结构应该是透明的。

不幸的是,Java除了行号之外,不会向您显示变量的名称或错误的确切位置。但是,如果使用Eclipse,则可以使用可为空的注释,请参见示例。请参阅以了解其他注释系统。

对我来说,最有效的方法是捕获通常抛出的异常,然后使用日志查看其中是否有“null”值

我的代码:

 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);
             }

您可以考虑JDK 14,它应该包括:

JEP358:有用的NullPointerException 假设此代码中出现NPE:

a.b.c.i = 99;
a[i][j][k] = 99;
文件名和行号不能准确指出哪个变量为空。
a
还是
b
还是
c

阵列访问和分配也会出现类似的问题。假设此代码中出现NPE:

a.b.c.i = 99;
a[i][j][k] = 99;
文件名和行号不能准确指出哪个数组组件为空。
a
还是
a[i]
还是
a[i][j]

说明: 如果更复杂的语句
a.b.c.i=99
抛出一个NPE,消息将剖析该语句,并通过显示导致null的完全访问路径来查明原因:

再次:使用JDK14进行测试


加上:


对于表达式
a[i][j][k]
,也有可能,
i
j
k
的类型为
整数且为空,因此取消装箱失败

在现实生活场景中,
=
右侧的表达式也可能具有NPE的潜力

我试过使用jdk-14.0.1

它起作用了;它会产生一个类似于

Cannot invoke "java.lang.Integer.intValue()" because "i" is null then.
当编译方法时没有调试信息,它将使用类似“
”的内容而不是“
i
”,但这是不可避免的


嗯,如果不是一行的话,找到NullPointerException会更容易。遵循这样的代码真的很难。考虑到您的选择,我只想指出“太多的工作”从长远来看可能意味着更少的工作。将其转化为适当的块。你很快就会发现问题。别忘了使用异常作为控制流机制是一件非常糟糕的事情……10年后,JEP 358将有所帮助:看,仅仅因为东西串在一起,并不意味着你违反了德米特定律。主要是通过链接获取引用,然后修改某些内容。向下以只读方式显示或比较值没有什么错。>什么