找出以编程方式抛出NullPointerException的变量

时间:2010-04-19 13:55:10

标签: java debugging nullpointerexception

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

  • if (var==null) - >太多的工作
  • try { ... } catch (NullPointerException e) { ...} - >它告诉我什么行抛出异常
  • 使用调试器 - >用手,太慢了

考虑这行代码:

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

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

8 个答案:

答案 0 :(得分:27)

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

throw new NullPointerException();

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

您最好的选择是尽可能少地在每一行上添加语句,以便明显导致空指针异常的原因。考虑在问题中重构代码,看起来像这样:

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

确保更多的代码行。但它也更具可读性和可维护性。

答案 1 :(得分:6)

很抱歉,不,没有一种简单的编程方式来确定哪个变量或方法调用是异常的来源。您可以使用Aspect-Oriented Programming (AOP)之类的内容,例如AspectJ,但这不是语言固有的,并且通常不会仅仅为了调试目的而合并到程序中。

  • if (var==null) -> too much work
  • try { } catch() { }
  • Debugger

我知道你不想听到这个,但这些只是开展业务的成本。

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

看到如此多的串联方法调用是不常见的。我相信你最好的选择就是养成更多打破这些的习惯 - 每行不要低至1个电话,但要少于此。为什么呢?

1)Correctness - 在这些调用之一的设计中它是否有效返回null?如果是这样,你应该将其分解,测试并适当地处理它。

2)Understandability - 对于未来的维护者(包括 future your )来说,如果你是中间的,命名良好的变量来帮助澄清这一行上发生的事情,将更容易理解。

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

4)Debugging - 正如你的问题所指出的那样,将这样一条复杂的线路分开可以简化调试。通过缩小异常的可能来源。

答案 2 :(得分:2)

“使用调试器 - >手动,太慢”是什么意思?如果您的代码结构合理,那么在同一行上使用的变量不会超过两个或三个。检查它们是否太慢了?你每分钟都没有NullPointers。

答案 3 :(得分:2)

您可以考虑将JDK 14作为announced here,其中应包括the JEP 358

  

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)

再次:将在JDK 14上进行测试。

答案 4 :(得分:1)

我知道你提出(var==null)工作太多了,但是,正如Miguel在评论中所说的那样,这就是我要用的。

答案 5 :(得分:1)

我认为您应该注意Demeters Law

没有多少人严格遵守它,因为它导致了许多委托方法 但是离它太远会导致对内部结构的依赖,这应该是透明的。

答案 6 :(得分:0)

不幸的是,Java不会向您显示变量的名称或除行号之外的错误的确切位置。如果您使用Eclipse,则可以使用可为空的注释,例如,请参阅http://www.fosslc.org/drupal/content/bye-bye-npe。有关其他注释系统,请参阅Which @NotNull Java annotation should I use?

答案 7 :(得分:0)

对我来说真正有效的方法是捕获通常被抛出的异常,然后使用Log查看它们中是否有任何“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);
             }