1

假设您的 Java 代码如下所示:

getPerson().getParent().getSiblings().first().getName()

并且您在该行上得到一个 NullPointerException。你怎么知道哪个是空的?您可以调试它并检查每个调用,或者您可以暂时将链接拆分为多行。

但是,我记得不久前看到一个开源项目,它可以运行,我认为它是一个 javaagent,它可以为 NullPointerException 提供更好的堆栈跟踪,它提供返回 null 结果的方法调用。不幸的是,我似乎找不到它。有谁知道那将如何完成,或者它是什么工具?

4

5 回答 5

1

IMHO it is a better style when you don't put in one line methods which may throw npe. Then you don't have such a problem :) Even putting each invocation in a single line (but the same instruction like method1()\n.method2() and so one) is not a good idea. Simple code reformatting can put them back in one line.

If method may return null you should really check the return value each time. If the method should not return null, the getter should contain a check and throw an exception (IllegalStateException?) instead of returning null.

You can add to existing code such a check with AspectJ and load-time veave (using javaagent).

For example:

/** Throw Error if a method for creating a Point returns null */
after () returning (Point p) : 
    call(Point+ SubPoint+.create(..)) {
    if (null == p) {
        String err = "Null Point constructed when this (" 
            + thisJoinPoint.getThis() 
            + ") called target (" 
            + thisJoinPoint.getTarget() 
            + ") at join point (" 
            + thisJoinPoint.getSignature() 
            + ") from source location (" 
            + thisJoinPoint.getSourceLocation()
            + ") with args ("
            + Arrays.asList(thisJoinPoint.getArgs())
            + ")";
        throw new Error(err);
    }
}
于 2011-07-22T15:27:24.623 回答
1

有趣的。

一个人可以有一个空父母吗?(有性生殖的生物不是有两个父母吗?)

如果你是独生子怎么办?getSiblings() 应该返回什么?null 或者,更好的是,一个空集合?

如果你没有名字怎么办?斯汀或麦当娜是名字还是姓氏?如果首先,姓氏返回什么?

这里真正的问题是设计。您还没有充分考虑在 null 的情况下该怎么做。最好弄清楚这一点。

于 2011-07-22T15:33:14.270 回答
0

我认为有些人可能会使这比 OP 要求的复杂得多

您所要做的就是将每个链接的方法放在自己的行上。

getPerson()
.getParent()
.getSiblings()
.first()
.getName();

您将获得正确的行号,该行号将指示 NPE 是哪种方法(上一行返回 null)。

是的,您可以进行各种强大的 NPE 检查,但在一天结束时,有时您只需要完成一些事情,而 null 可能不是预期的,所以不要用其他一些错误处理来粉饰它。

您还可以通过在对象及其子对象上添加验证注释来防止这种情况发生。验证对象,然后继续遍历对象树。这在过去对我来说效果很好。这将为您提供更好的自动可重用错误处理。另外,您正在记录哪些方法可以返回 null。

说支持链接的糟糕设计我认为是不公平的,因为最流行的 Javascript (jQuery) 库之一一直在使用它(是的,它有时会返回 null/undefined 值)。

于 2011-07-22T15:39:35.573 回答
0

理想情况下,您会将每个方法的返回值分配给一个变量,这样您就可以检查它们;无论如何,这就是编译器在内部对临时变量所做的事情。

如果您不想重写,您可以在该行设置一个断点,然后为每个函数添加一个监视(最简单),或者(如果您的 IDE 支持)逐个键入每个函数时间进入“立即”窗口,看看会发生什么。

于 2011-07-22T15:30:14.267 回答
0

我的观点是,这是一个简洁代码优于可维护代码的问题。链接函数可能会使代码看起来更干净,但会导致代码库难以长期维护。如果您将操作分开,您可能会拥有更长的功能,但追踪错误应该会容易得多。

于 2011-07-22T15:34:03.940 回答