我的代码中有一个情况,我在其中进行了大约5次链式get调用,并且任何这些get调用都可以返回null值。我希望它不必那样,但这就是我消耗的服务如何返回我请求的对象,所以我必须处理它。
最初,我的代码看起来像这样:
String firstDomain = book.getBookImages().getDomains().getDefaults().getDomain().get(0);
不幸的是,该行容易出现空指针和arraylist超出范围的异常。我知道我必须检查空指针,但我试图决定
一个。这样做效率最高的代码
和
B中。这样做的最佳代码
一种选择是分配大量引用,然后检查空值。像这样:
BookImages bImages = book.getBookImages();
Domains domains = null;
Defaults defaults = null;
List<String> domain = null;
String firstDomain = null;
if (bImages != null) {
domains = bImages.getDomains();
if (domains != null) {
defaults = domains.getDefaults();
if (defaults != null) {
domain = defaults.getDomain();
if (domain != null && domain.size() > 0) {
firstDomain = domain.get(0);
}
}
}
}
if (firstDomain == null) {
throw new IncompleteBookException("The book was incompletely attributed.");
}
我认为这非常有效,但它困扰我有多少行。它超过了它所属方法的长度的两倍。
这是我能想到的另一种选择:
if (book.getBookImages() == null || book.getBookImages().getDomains() == null || book.getBookImages().getDomains().getDefaults() == null || book.getBookImages().getDomains().getDefaults().getDomain() == null || book.getBookImages().getDomains().getDefaults().getDomain().size() < 1 || book.getBookImages().getDomains().getDefaults().getDomain().get(0) == null) {
throw new IncompleteBookException("The book was incompletely attributed.");
}
我喜欢这样的事实,那就是只有三行,即使一行非常荒谬,但我不确定Java的运行时或编译器是否会优化那些重复的方法调用。
我也对其他更好的解决方案持开放态度。有谁知道这些选项中的一个或另一个是否会比另一个更好,或者这是一个微观优化,甚至懒得思考它是愚蠢的,我应该只使用对我来说更好看的?对于不同的事情,我可能不得不多次这样做。
答案 0 :(得分:2)
要遵循您的第二种方法,您可以申请:
if ((bImages=book.getBookImages()) == null
|| (domains=bImages.getDomains()) == null
|| (defaults=domains.getDefaults()) == null
|| (domain=defaults.getDomain()) == null
|| domain.size() < 1
|| (firstDomain=domain.get(0)) == null) {
throw new IncompleteBookException("The book was incompletely attributed.");
} else {
//here you can use the firstDomain variable, that is set with the correct value
}
这样做更好,因为你避免了多个(无用的)相同的调用,并且你已经在变量firstDomain中设置了正确的值(当然,只有在没有空的情况下等等......)
答案 1 :(得分:1)
如果代码更长且错误更短,则不必过多担心代码的长度。编程的目标不是编写尽可能短的代码(除了一些比赛等)。
你的第一个(更长的)方式是正确的,即使有点长。
第二种方法将重复调用同一方法。这可能是您可能想要避免的 - 它可能会产生不良影响,而且性能会更差。
答案 2 :(得分:1)
正如Szymon指出的那样,你不应该两次调用同样的方法。
通过将所有嵌套null
检查合并为一个来使原始解决方案更具可读性:
BookImages bImages = null;
Domains domains = null;
Defaults defaults = null;
List<String> domain = null;
String firstDomain = null;
if ((bImages = book.getBookImages()) != null
&& (domains = bImages.getDomains()) != null
&& (defaults = domains.getDefaults()) != null
&& (domain = defaults.getDomain() != null
&& domain.size() > 0) {
firstDomain = domain.get(0);
}
答案 3 :(得分:1)
尝试使用布尔方法;他们倾向于使逻辑更简单,更清晰;例如,我会这样做:
public boolean isCompletelyAttributed(BookImages bImages) {
if (bImages == null) return false;
if (bImages.getDomains() == null) return false;
if (bImages.getDomains().getDefaults() == null) return false;
if (bImages.getDomains().getDefaults().getDomains() == null) return false;
return bImages.getDomains().getDefaults.getDomains.size() > 0;
}
然后你打电话
if (!isCompletelyAttributed(book.getImages())) {
throw new IncompleteBookException("The book was incompletely attributed.");
}
我还建议您在布尔方法中使用Nicola或kiruwka的解决方案。我不知道你可以在对它们做逻辑时重新分配变量,但这似乎是一个优雅的解决方案。
答案 4 :(得分:-1)
这是一种简短的方法。但是,嘿,我不知道你所建造的具体细节以及这是否适合你。
try {
String firstDomain = book.getBookImages().getDomains().getDefaults().getDomain().get(0);
// operate on firstDomain
} catch (NullPointerException e) {
throw new IncompleteBookException("The book was incompletely attributed.");
} catch (IndexOutOfBoundsException e) {
throw new IncompleteBookException("The book was incompletely attributed.");
}
我听说人们关心这类事情的表现,因为VM必须填写NullPointerException
的堆栈跟踪。在这种情况下,您已经为IncompleteBookException
进行了类似的操作。