让我说我有以下课程:
public class RectangularPrism{
public Integer width;
public Integer height;
public Integer depth;
//setters and getters
}
我用它来计算所有棱镜的体积总和。我有两种计算方法。哪一个更好?
这个使用条件运算符。
public Integer volumeSum(List<RectangularPrism> prismList){
Integer sum = 0;
for(RectangularPrism prism: prismList){
Integer width = prism.getWidth() == null ? 0 : prism.getWidth();
Integer height = prism.getHeight() == null ? 0 : prism.getHeight();
Integer depth = prism.getDepth() == null ? 0 : prism.getDepth();
sum += width * height * depth;
}
return sum;
}
这个使用尝试捕获块
public Integer volumeSum(List<RectangularPrism> prismList){
Integer sum;
for(RectangularPrism prism: prismList){
try {
Integer width = prism.getWidth();
Integer height = prism.getHeight();
Integer depth = prism.getDepth();
sum += width * height * depth;
}catch( NullPointerException e){}
}
return sum;
}
哪一个会更好如果我的班级有100个或更多的字段来决定结果?
使用尝试捕获来处理 null 值是否可以?
答案 0 :(得分:13)
这在每个级别都是一个坏主意。
try-catch
实际上更慢(如果确实有异常抛出)try-catch
区块中的任何其他内容抛出合法的NPE,则无法告知发生了什么。 (想象一下例如prism
本身为空时的情况。)?:
运算符检查空值是一个众所周知的模式,每个人都会认识到。catch
块是一个很大的禁忌,可能是最可靠的生成错误的方法,需要花费很长时间来追踪。null
值将意味着将跳过try
块的其余部分。当然sum
仍然是正确的,但这只是巧合。如果您真的想提高性能,请不要使用Integer
和其他包装类进行简单计算,而是使用相应的原语(在本例中为int
)。额外的好处是你突然不必再担心null
了,因为原始值永远不会是null
。
说真的,不要。每次你这样做,一只可爱的小猫死了。
答案 1 :(得分:3)
您永远不应该使用try-catch
来处理程序的控制流程。
始终使用已建立的方法,在这种情况下,请检查第一个代码示例中的null。
答案 2 :(得分:0)
我知道这不会回答这个问题(可以try .. catch
用于代码优化),但我认为你应该很少考虑null
值:你应该强制执行(width
,height
,depth
)如果是对象的固有属性,则为非null
。
我的意思是,您正在构建RectangularPrism
:width
,height
和depth
来定义此对象。你不能在那里null
,因为否则它不会是一个矩形棱镜。
在这种情况下,我宁愿这样做:
public class RectangularPrism {
private final Integer width;
private final Integer height;
private final Integer depth;
public RectangularPrism(Integer width, Integer height, Integer depth) {
this.width = Objects.requireNonNull(width, "width");
this.height = Objects.requireNonNull(height, "height");
this.depth = Objects.requireNonNull(depth, "depth");
}
// getters
}
或者使用setter:
public class RectangularPrism {
public Integer width;
public Integer height;
public Integer depth;
public void setWidth(Integer width) {
this.width = Objects.requireNonNull(width, "width");
}
}
您不必处理null
,因为JVM会抛出NullPointerException
,但只有因为对象未完全/正确初始化,不是因为你没有处理不应该存在的null
值。这是抛出IllegalStateException
的正常行为,因为对象处于不应该处于的状态(此处:因为您有null
个值)。
要完成,如果卷计算是RectangularPrism
上的操作而不是外部操作,则会有更好的实现。
这种方式会更正确:
public class RectangularPrism {
private final Integer width;
private final Integer height;
private final Integer depth;
public RectangularPrism(Integer width, Integer height, Integer depth) {
this.width = Objects.requireNonNull(width, "width");
this.height = Objects.requireNonNull(height, "height");
this.depth = Objects.requireNonNull(depth, "depth");
}
public Integer computeVolume() {
return width * height * depth; // can't be null.
}
}
然后(我在那里使用int
,因为有一个总和,我不会评论原语在包装类上的使用):
public Integer volumeSum(List<RectangularPrism> prismList) {
int initial = 0;
for (RectangularPrism p : prismList)
initial += p.computeVolume();
return initial;
}
最后但并非最不重要的是,异常处理速度较慢,但循环中的异常处理速度较慢。