【问题标题】:Android NullPointerException - Debugging a specific lineAndroid NullPointerException - 调试特定行
【发布时间】:2015-07-17 06:57:18
【问题描述】:

如果我有这样的一行:

var.getSomething().getSomethingElse().setNewValue(stuff.getValue().getWhatever());

如果该行创建了一个NullPointerException,有没有办法找出哪个方法返回了一个null值?

我相信我能够在每个点处分割线并获得显示哪条线失败的异常。但我不能再让它工作了(也许我记错了)。

这样写是唯一的调试方法吗?

a = var.getSomething();
b = a.getSomehingElse();
c = stuff.getValue();
d = c.getWhatever();
b.setNewValue(d);

有了这个,我应该能够很容易地看到异常发生在哪里。但是这样写感觉效率低下又丑陋。

我使用 Android Studio。以前用过 Eclipse,前段时间改用 Android Studio。

【问题讨论】:

  • 为什么不用调试器来估计每个调用的值?
  • 在 Eclipse 中,您可以在 Debug-Mode 中选择特定部分,而不是右键单击“inspect”,然后从该部分获取返回值。
  • 我相信 logcat 可以显示 NPE 的确切位置。 (IMO) 你必须遵守日志。
  • 我可能应该更好地阅读调试工具。我使用 android-studio 并且大多数这些异常都很难重现。通常,用户设法以一些奇怪的方式获得这些异常。所以在我的硬件上调试可能很困难。不,我只看到 logcat 显示的不是行号。
  • 在 android studio 中,只需在调试模式下以相同的运行配置运行,当你来到这一行时,行中的每个值都会被写入。您也可以右键单击并评估鼠标选择的表达式。安静直接。

标签: java android debugging nullpointerexception


【解决方案1】:

您可能希望将每个部分都放入“手表”中:

但我很确定 Eclipse 和 Android Studio 都可以让您通过选择您感兴趣的部分来检查内容(如果您处于调试模式)

【讨论】:

  • 谢谢。这是最接近解决方案的方法。我设法重现了异常,然后这有所帮助。问题在于如何重现错误。为了做到这一点,我似乎必须将我的行分成多个较短的行,以便我可以准确地确定异常发生的位置。
【解决方案2】:

我能给你的最好建议是对所有具有返回值的方法使用@Nullable@NonNull 注释。它不会帮助您获得空指针所在的行,但有助于防止将来出现这种情况。

因此,如果方法可能返回 null 并且您在调用序列中有它,您将收到来自 Android Studio 的警告。在这种情况下,最好中断序列并检查null

例如:

private static class Seq {

    private final Random rand = new Random();

    @NonNull
    public Seq nonNull() {
        return new Seq();
    }

    @Nullable
    public Seq nullable() {
        return rand.nextInt() % 100 > 50 ? new Seq() : null;
    }

}

如果你写new Seq().nonNull().nonNull().nullable().nonNull();,你会收到来自IDE的警告:

Method invocation `new Seq().nonNull().nonNull().nullable().nonNull()` may produce 'java.lang.NullPointerException'

在这种情况下,最好的解决方案是像这样更改代码:

    Seq seq = new Seq().nonNull().nonNull().nullable();
    if (seq != null) {
        seq.nonNull();
    }

别忘了将它添加到 Gradle 构建脚本中

compile 'com.android.support:support-annotations:22.+'

【讨论】:

  • 我喜欢这个主意。但我不认为我可以在我的应用程序中应用它。不过以后可能会用到。谢谢!
【解决方案3】:

我对你的做法并不肯定。这使您的代码紧密耦合且不可单元测试。

var.getSomething().getSomethingElse().setNewValue(stuff.getValue().getWhatever());

改为做类似的事情

var.getSomething();

在内部得到的东西会做你正在做的任何事情

getSomethingElse().setNewValue(stuff.getValue().getWhatever())

getSomethingElse() 应该以同样的方式执行您作为其中一部分所做的任何事情

setNewValue(stuff.getValue().getWhatever())

【讨论】:

    猜你喜欢
    • 2020-06-12
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-07
    • 2018-08-11
    • 1970-01-01
    相关资源
    最近更新 更多