我喜欢 Java 中的Optional
。它在一个简单的类中使我能够清楚地识别可能可用或不可用的返回类型和参数。
我遇到的一件事是必须将其分配给一个短期变量,然后将其继承到每个后续作用域中。
在使用这样的选项时,我喜欢使用简单的变量名opt
:
Optional<ThingA> opt = maybeGetThing();
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
...
但是当我需要在此范围内使用变量名时......
void method() {
Optional<ThingA> opt = maybeGetThing();
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// Duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
}
}
我可以使用 optA
和 optB
等。但我想知道是否有另一种方法可以编写此代码而不必枚举我的临时变量。这有点像 a
aaaa
aaaaaabbb
之类的惰性变量名称。
我不想像这样明确命名我的所有选项:
Optional<ThingA> optUsefulVariableName = maybeGetThing();
if (optUsefulVariableName.isPresent()) {
ThingA usefulVariableName = optUsefulVariableName.get();
...
虽然准确,但非常冗长。我还尝试使用像 opt
和 i
这样的一次性名称来表明这些实际上只是临时的,不应该在其直接范围之外发挥任何作用(即使它们将被继承) )。
更新:
我已经看到了使用 ifPresent()
的建议,但我不知道如何在可选为空时我还需要执行操作的情况下使用它:
void method() {
Optional<ThingA> opt = maybeGetThing();
if (!opt.isPresent()) {
doSomethingOnlyHere();
return;
}
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// Duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
}
}
当我尝试使用 ifPresent()
重构时:
void method() {
// Doesn't handle instance where I need side effects on an empty optional
maybeGetThing().ifPresent(usefulVariableName -> {
...
}
}
最佳答案
消除变量和调用 Optional#get
的需要的最基本方法是使用 Optional.ifPresent
,如果Optional有值,它会调用一个函数。
maybeGetThing().ifPresent(val -> {
// do stuff with side effects here
});
这仍然是使用Optional的一种相当有限的方式,因为Optional的关键目的之一是促进函数式编程。如果您是初学者,这可能会让您有点迷失,但我们的想法是让函数返回一些内容,而不是依赖 side effects 的函数。 。依赖副作用的函数不能链接在一起,并且通常更难以推理。
从技术上讲,可选
是一种称为仿函数(来自范畴论)的东西。它是一个值的包装器(无论 T
是什么),它允许该值通过一系列操作来对其进行操作,并将其传递到下一个操作,直到我们得到我们想要的,然后操作链以终端(即最终)操作结束。如果存在,终端操作可能会返回展开的值,如果不存在,则可能会抛出或返回一些默认值。
对于Optional,如果该值不存在,它将跳过任何后续操作。
有常见的操作,如map、filter、flatMap(好吧,这是一个 Monad 操作)以及其他更多 java 特定操作,如 Optional#orElse
和 Optional#orElseThrow
。
要重构您的示例代码,您可以这样做。
void method() {
return maybeGetThing().flatMap(val -> {
// eek side effects
val.doA();
val.doB();
val.doC();
return val.maybeAnotherThing();
});
}
flatMap
是一种将一种类型的可选值转换为另一种类型的可选值的方法。如果返回值不是可选的,您将使用 map 。
您可以看到,我们不再需要返回值的名称,而是为 lambda 函数的参数命名。 lambda 函数是有作用域的,因此您可以根据需要重用这些名称。
我通常喜欢提供可运行的代码,因此这里是一个人为的示例来说明我的意思是可运行的。
import java.util.Optional;
class DummyClass {
private int val = 0;
public void doA(){ val += 1; }
public void doB(){ val += 2; }
public void doC(){ val += 3; }
public Optional<String> maybeAnotherThing(){
return Optional.of(Integer.toString(val));
}
}
public class UseOptional5 {
Optional<DummyClass> maybeGetThing(){
return Optional.of(new DummyClass());
}
String method() {
return maybeGetThing()
// you can put other operations here
.flatMap(val -> {
// eek side effects
val.doA();
val.doB();
val.doC();
return val.maybeAnotherThing();
})
// you can put other operations here too
.orElseThrow(() -> new IllegalArgumentException("fail!!"));
}
public static void main(String args[]) {
UseOptional5 x = new UseOptional5();
System.out.println(x.method());
}
}
关于java - 有没有更清晰的方法来处理短暂的选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57281593/