在Java 8中,如果Optional
存在,是否有办法强制方法返回?
我猜这个答案是否定的。但是,如何避免在以下代码中使用isPresent()
和get()
?
public Bar myMethod(){
if(condition){
Optional<Foo> foo = getOptionalFoo();
if(foo.isPresent()){
return foo.get().getBar();
}
}
return getOtherBar();
}
一种解决方案是写:
public Bar myMethod(){
if(condition){
return getOptionalFoo()
.map(Foo::getBar)
.orElseGet(() -> getOtherBar());
}
return getOtherBar();
}
但这似乎不是一个好主意,因为现在我们写了两次调用getOtherBar
。有没有办法避免这种情况?
public Bar myMethod(){
//Or a ternary operator but there are hard to read when they make long lines
Optional<Foo> foo;
if(condition){
foo = getOptionalFoo();
} else {
foo = Optional.empty();
}
return foo.map(Foo::getBar)
.orElseGet(() -> getOtherBar());
}
但问题在于我们为它创建了一个无用的空Optional
和链方法。如果在99%的情况下不满足条件,这会使其效率远低于原始代码(特别是如果我们有多个map()
和filter()
)。
注意:我给出了一个基本的例子,实际上在我们的代码中我们有更多的条件依赖于其他调用的结果(取决于foo)。
答案 0 :(得分:3)
这个怎么样?下面代码的形式更强可读但慢比你的更强,因为如果不满足condition
,getOtherBar()
还需要额外的map
上的操作(orElseGet
&amp; Optional
)。
public Bar myMethod() {
Optional<Foo> source = condition ? getFoo() : Optional.empty();
return source.map(Foo::getBar)
.orElseGet(this::getOtherBar);
}
但是,如果像上面那样有很多重复,那么你可以通过提取方法来释放自己,例如:
private Optional<Foo> foo(){
return condition ? getFoo() : Optional.empty();
}
public Bar myMethod() {
return foo().map(Foo::getBar).orElseGet(this::getOtherBar);
}
public Other otherMethod() {
return foo().map(Foo::getOther).orElseGet(this::getOther);
}
答案 1 :(得分:3)
什么是condition
?由于它位于实例方法中,因此它必须是一个条件,具体取决于实例的状态。为简单起见,假设这是您班级的一个领域,那么您可以编写
public Bar myMethod() {
return Optional.of(this)
.filter(obj -> obj.condition)
.flatMap(ClassContainingMyMethod::getFoo)
.map(Foo::getBar)
.orElseGet(this::getOtherBar);
}
如果getFoo()
不贵并且没有副作用,即使您不打算使用其结果,也可以接受始终调用它,具体取决于condition
。这将简化代码
public Bar myMethod() {
return getFoo()
.filter(foo -> condition)
.map(Foo::getBar)
.orElseGet(this::getOtherBar);
}
请注意,原始代码存在语义差异。当getBar
返回null
时,原始代码会返回null
,而使用带有Optional.map
结果的函数的getBar()
的所有代码都将返回调用{ {1}}。
答案 2 :(得分:2)
一旦你进入Optional
心态,并使用三元运算符来处理你的病情,这很容易就会崩溃。
public Bar myMethod(){
return ( condition ? getOptionalFoo() : Optional.<Foo> empty())
.map(f -> f.getBar())
.orElseGet(() -> getOtherBar())
}