假设你有类似的Java代码:
getPerson().getParent().getSiblings().first().getName()
你在那一行得到一个NullPointerException。你怎么知道哪一个是空的?您可以调试它并检查每个呼叫,或者您可以暂时将链接拆分为多行。
但是,我记得刚才看到一个开源项目会运行,我认为它是一个javaagent,它会为NullPointerException提供更好的堆栈跟踪,它给出了返回null结果的方法调用。不幸的是我似乎无法找到它。有谁知道怎么做,或者它是什么工具?
答案 0 :(得分:1)
恕我直言,当你没有放入可能引发npe的一行方法时,这是一种更好的风格。然后你没有这样的问题:)甚至把每个调用放在一行(但是像method1()\ n.method2()那样的一个相同的指令)并不是一个好主意。简单的代码重新格式化可以将它们放回一行。
如果方法可能返回null,那么每次都应该检查返回值。如果该方法不应返回null,则getter应包含一个检查并抛出异常(IllegalStateException?)而不是返回null。
您可以使用AspectJ和load-time veave(使用javaagent)向现有代码添加此类检查。
例如:
/** 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);
}
}
答案 1 :(得分:1)
有趣。
一个人可以有一个空父母吗? (不要在性生殖中有两个父母吗?)
如果你是独生子女怎么办? getSiblings()应该返回什么? null,或者更好的是,一个空集合?
如果您没有名字怎么办? Sting或Madonna是名字还是姓?如果是的话,姓氏会返回什么?
这里真正的问题是设计。你没有想过在nulls的情况下该怎么做。最好搞清楚。
答案 2 :(得分:0)
理想情况下,您可以将每个方法的返回值分配给变量,这样您就可以检查这些变量;这就是编译器内部使用临时变量所做的事情。
如果您不想重写,可以在该行上设置断点,然后为每个函数添加一个监视(最简单),或者(如果您的IDE支持它)键入每个函数1-at - 进入“即时”窗口的时间,看看会发生什么。
答案 3 :(得分:0)
我的观点是,这是一个简洁的代码而不是可维护代码的问题。链接功能可能会使代码看起来更干净,但可能会导致代码库长期难以维护。如果您将操作分开,则可能会有更长的功能,但追踪错误应该更加容易。
答案 4 :(得分:0)
我认为有些人可能会比OP要求的更复杂
您所要做的就是将每个链式方法放在自己的行上。
getPerson()
.getParent()
.getSiblings()
.first()
.getName();
您将得到正确的行号,它将指示NPE的哪个方法(前一行返回null)。
是的,你可以做各种强大的NPE检查,但在一天结束的时候有时候你需要完成任务并且可能没有预期null,所以不要用其它错误处理来覆盖它。
您还可以通过在对象及其子对象上添加validation annotations来防止这种情况发生。验证对象然后继续遍历对象树。这对我来说过去很有用。这将为您提供更好的自动可重用错误处理。另外,您正在记录哪些方法可以返回null。
说它的糟糕设计支持链接我不认为是公平的,因为最流行的Javascript(jQuery)库之一一直使用它(是的,它有时会返回null / undefined值)。