找出哪个变量以编程方式抛出 NullPointerException

2022-09-01 11:42:54

我知道我可以使用以下技术找出Java中的变量是否为空:

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

请考虑以下代码行:

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

我想知道是否有一种通用方法可以程序化地找出哪个变量(不仅仅是行)在某个代码区域中抛出NullPointerException。在示例中,知道


答案 1

由于有可能在不涉及变量的情况下导致空指针异常:

throw new NullPointerException();

我不得不说,没有通用的方法可以将空指针异常固定到特定变量。

最好的办法是在每行上放置尽可能少的语句,以便导致空指针异常的原因变得明显。请考虑重构问题中的代码,使其如下所示:

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

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


答案 2

您可以考虑,正如这里宣布的那样,JDK 14应该包括JEP 358

JEP 358:有用的 NullPointerExceptions

假设 NPE 出现在以下代码中:

a.b.c.i = 99;

文件名和行号不能准确定位哪个变量为 null。
是还是?abc

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

a[i][j][k] = 99;

文件名和行号不能准确定位哪个数组组件为 null。
是还是?aa[i]a[i][j]

描述:

如果更复杂的语句引发 NPE,则消息将剖析该语句,并通过显示导致 null 的完整访问路径来查明原因:a.b.c.i = 99;

Exception in thread "main" java.lang.NullPointerException: 
        Cannot read field "c" because "a.b" is null
    at Prog.main(Prog.java:5)

再次:使用JDK 14进行测试。


Holger在评论中补充道

对于表达式 ,还有一种可能性是, , 或 具有类型并且为 null,因此取消装箱失败。a[i][j][k]ijkInteger

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

我尝试使用jdk-14.0.1

它的工作原理;它产生一条消息,如

Cannot invoke "java.lang.Integer.intValue()" because "i" is null then.

当在没有调试信息的情况下编译方法时,它将使用类似“”而不是“”的内容,但这是不可避免的。<local8>i