如果我有一个像
class A
{
Private B b;
X getX()
{
X x = b.newClient().call();
}
}
我应该在这里检查 b 是否为 null 吗?这应该如何处理?使用异常(例如,这实际上不是一个参数,所以在这里抛出一个非法参数有意义吗?或者只是记录一个错误?
如果我有一个像
class A
{
Private B b;
X getX()
{
X x = b.newClient().call();
}
}
我应该在这里检查 b 是否为 null 吗?这应该如何处理?使用异常(例如,这实际上不是一个参数,所以在这里抛出一个非法参数有意义吗?或者只是记录一个错误?
private B b
是您隐藏的内部实现的一部分(即它不是您班级的客户使用的公共 API 的一部分)。因此,b
无效的不是客户的问题,而是您作为课程开发人员的问题。
想象一下,如果您尝试使用一些从 GitHub 上下载的闪亮的新库:
MagicAnythingParser parser = new MagicAnythingParser();
parser.parse(myDocument);
并且调用parse
引发了一个异常,即"intakeManifold is null"
. 你会想“到底是什么?!”
您几乎不知道,您应该首先拨打以下电话:
parser.setupParseRules(someRuleset);
在内部,这创建了一些对象并将其分配给intakeManifold
.
更好的情况是,如果MagicAnythingParser
能很好地跟踪其内部状态,而是抛出类似IllegelStateException("No parse rules applied. You must call setupParseRules first.")
我的全部观点是,你应该开发你的类的公共 API,考虑到客户(即使那个客户是你。)尽量确保你的对象总是处于“良好状态”——当你不能时,抛出有意义的例外,这使得问题所在的问题一目了然。
你有处理空指针可能性的策略吗?即,如果变量永远不应该为空,因此表明存在错误,那么您可能不想隐藏它。我喜欢让系统在我面前炸毁,以便快速发现故障并轻松确定根本原因。
如果您的代码设计为无论如何都可以继续运行,例如在处理批次时,并且您不希望批次项目中的一个错误杀死整个批次,那么您可以记录它或其他什么。但除此之外,就让 NPE 去做吧。
在getX中检查b是否为空并不会给你带来太多好处。您正在用一个运行时异常换另一个运行时异常。你真的很想知道为什么b为空。
我建议将b设为 final 并通过构造函数进行设置。在构造函数中执行 null 检查。