在 Kotlin 中获取或返回的可能性



我经常遇到Optional和类似类的问题,例如VAVROptionTryEither

假设我有一些Optional,如果它是空的,我想立即从方法返回(无一例外,因为我的方法也返回Optional,所以getOrElseThrow不在图片中),如果它存在,我想进一步处理它。

public Optional<Integer> converter() {
Optional<String> opt = getSomething();
if(!opt.isPresent())
return Optional.empty();
String value = opt.get();  
// some manipulations on value, such as map and flatMap would cause a huge mess
return Integer.parseInt(value);  
}

我只需要立即返回,以防值为空,我不能做map链和flatMap.整个痛苦都在做.get().像getOrElseThrow这样的东西,但用return而不是throw会很棒 -getOrElseReturn.显然在 Java 中是不可能的,所以我考虑在 Kotlin 中尝试一下。

fun safeOptional(): Optional<Int> {
val extracted = Optional.of("123")
.getOrElseReturn { return Optional.empty() }
val modified = extracted.toInt() * 2
return Optional.of(modified)
}
private inline fun <T> Optional<T>.getOrElseReturn(block: (Optional<T>) -> T): T {
return if (!this.isPresent)
block(this)
else
this.get()
}

令我惊讶的是,它实际上做了我想要的。如果我将Optional.of("123")更改为Optional.empty()它会立即从方法返回。我不明白它是如何编译的。

我的方法需要一个block: (Optional<T>) -> T,否则它将无法编译。所以就我而言,我有Optional<String>,我需要传递一个block: (Optional<String>) -> String,但是嘿 - 我拥有的块远不及此,它仍然可以编译,如何?

当我将块提取到变量时,它变得val block: (Optional<String>) -> Nothing(我想return语句是Nothing),它仍然编译,这让我更加惊讶。

顺便说一句,我知道这段代码并不是我想要的 - 有人可以在不非本地返回该方法的情况下传递另一个块,但我认为没有另一种方法

将方法的第二部分提取到另一个私有方法中并调用getSomething().map(this::otherPrivateMethod)

如果getSomething()中不存在任何值,则不会调用它

基本上

public Optional<Integer> converter() {
return getSomething().map(this::privateConverter); 
}
private Integer privateConverter(Integer integer) {
// some manipulations on value, such as map and flatMap would cause a huge mess
return Integer.parseInt(value);  
}

回答 Kotlin 部分:

fun safeOptional(): Optional<Int> {
val extracted = Optional.of("123")
.getOrElseReturn { return Optional.empty() } 
.......
}

这里的返回不是从 lambda 返回的,而是从函数safeOptional返回的,因此 lambda 不返回任何内容(它返回 Nothing)。Lambda 返回 任何内容都不能作为返回任何内容的 lambda 传递。

要获得编译错误,您应该改为从 lambda 返回:

val extracted = Optional.of("123")
.getOrElseReturn { return@getOrElseReturn Optional.empty() }

通常,在 Kotlin 中不需要 Optional 。应改用可为 null 的类型。您可以将它们与 nullsafe 运算符(例如 Elvis 运算符 --?:

fun nullsafe(x: String?): Optional<Int> {
val extracted = x ?: return Optional.empty()
val modified = extracted.toInt() * 2
return Optional.of(modified)
}
nullsafe("2") // => Optional[4]
nullsafe(null) // => Optional.empty

最新更新