我经常遇到Optional
和类似类的问题,例如VAVROption
,Try
,Either
。
假设我有一些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