假设我想访问类似
的内容productList.get(0).getCustomerList().get(0).getAddressList().get(0).getRegion.getCode()
在每个级别,我需要检查null或空列表。数据结构非常复杂,重构可能是一种选择,但也可能过于复杂或不可能。
结果代码为:
if(productList != null
&& !productList.isEmpty()
&& productList.get(0).getCustomerList().get(0) != null
&& ...){
return productList.get(0).getCustomerList().get(0).getAddressList(0).getRegion.getCode();
}
结果代码很丑陋,冗长,没有任何真正的业务逻辑,很难阅读。有一些聪明的方法来避免这种情况吗?是否可以接受:
try{
return productList.get(0).getCustomerList().get(0).getAddressList(0).getRegion.getCode();
} catch(NullPointerException | IndexOutOfBoundException e){
return null;
}
答案 0 :(得分:2)
我只是把它分成这样的东西:
Product p = getElementOrNull( productList, 0 );
if( p == null ) { return null; }
Customer c = getElementOrNull( p.getCustomerList(), 0 );
if( c == null ) { return null; }
Address a = getElementOrNull( c.getAddressList(), 0 );
if( a == null ) { return null; }
Region r = a.getRegion();
if( r == null ) { return null; }
return r.getCode();
带
<T> T getElementOrNull( List<T> list, int index ) {
if( list == null || index < 0 || index >= list.size() ) {
return null;
}
return list.get( index );
}
通常不建议使用异常来处理正常的代码流。你有时会看到它以这种方式完成,在某些情况下它会起作用,但它会使代码更难理解(什么可能是null或哪个索引可能是错误的)并且可能会混淆开发人员偶然发现你的代码并得出结论可以减少在其他情况下使用异常。
在您的情况下,您似乎可以确定链中的任何元素/列表为空,但假设地址必须始终具有区域或客户必须始终具有地址的情况。在这些情况下,您可以假设这些事情不为空,并调整空检查以引发更具描述性的异常(至少有更好的消息) - 这是你无法在“全能”捕获中做到的像你一样阻挡。
答案 1 :(得分:1)
这是使用Java 8 Optional的另一个建议。
Predicate<List> hasElement = list -> list != null && !list.isEmpty();
String code = Optional.ofNullable(productList)
.filter(hasElement).map(p -> p.get(0).getCustomerList())
.filter(hasElement).map(c -> c.get(0).getAddressList())
.filter(hasElement).map(a -> a.get(0).getRegion())
.map(Region::getCode)
.orElse(null);