如何在 scala 中重写此 java 函数以保持相同的可选输入参数?
How do I rewrite this java function in scala keeping the same Optional input parameter?
我在java
中有如下方法
protected <T> T getObjectFromNullableOptional(final Optional<T> opt) {
return Optional.ofNullable(opt).flatMap(innerOptional -> innerOptional).orElse(null);
}
它需要一个 java Optional
,它本身可以是 null
(我知道,这真的很糟糕,我们最终会解决这个问题)。它用另一个 Optional
包裹它,所以它变成 Some(Optional<T>)
或 None
。然后是flatMapped
,所以我们得到Optional<T>
或None
,最后应用orElse()
得到T
或null
。
如何在 Scala 中使用相同的 java.util.Optional 编写相同的方法?
protected def getObjectFromNullableOptional[T >: Null](opt : Optional[T]): T =
???
我试过了
protected def getObjectFromNullableOptional[T >: Null](opt : Optional[T]): T =
Optional.ofNullable(opt).flatMap(o => o).orElse(null)
但这给了我一个 Type mismatch
错误
Required: Function[_ >: Optional[T], Optional[NotInferedU]]
Found: Nothing => Nothing
我试过了
protected def getObjectFromNullableOptional[T >: Null](opt : Optional[T]): T =
Option(opt).flatMap(o => o).getOrElse(null)
但这给了我
Cannot resolve overloaded method 'flatMap'
编辑 我忘了说我使用的是 scala 2.11。我相信@tefanobaghino 的解决方案适用于 scala 2.13,但它引导我走向正确的道路。我把我的最终解决方案放在这个解决方案下面的评论中
最后一个错误引起了一些怀疑:看起来你在 Scala Option
中包装了 Java Optional
。相反,我本来希望这会失败,因为你试图 flatMap
到不同的类型,比如
error: type mismatch;
found : java.util.Optional[T] => java.util.Optional[T]
required: java.util.Optional[T] => Option[?]
这似乎可以满足您的要求:
import java.util.Optional
def getObjectFromNullableOptional[T](opt: Optional[T]): T =
Optional.ofNullable(opt).orElse(Optional.empty).orElse(null.asInstanceOf[T])
assert(getObjectFromNullableOptional(null) == null)
assert(getObjectFromNullableOptional(Optional.empty) == null)
assert(getObjectFromNullableOptional(Optional.of(1)) == 1)
你可以玩这个here on Scastie。
请注意,asInstanceOf
被编译为强制转换,而不是实际的方法调用,因此此代码不会抛出 NullPointerException
。
您还可以通过稍微帮助 Scala 的类型推断来更接近您的原始解决方案:
def getObjectFromNullableOptional[T](opt: Optional[T]): T =
Optional.ofNullable(opt).flatMap((o: Optional[T]) => o).orElse(null.asInstanceOf[T])
或者使用 Scala 的 identity
:
def getObjectFromNullableOptional[T](opt: Optional[T]): T =
Optional.ofNullable(opt).flatMap(identity[Optional[T]]).orElse(null.asInstanceOf[T])
对于使用 Scala 的解决方案 Option
你可以做一些非常接近的事情:
def getObjectFromNullableOption[T](opt: Option[T]): T =
Option(opt).getOrElse(None).getOrElse(null.asInstanceOf[T])
请注意,使用 Scala 的 Option
转到您的 flatMap
解决方案可以避免必须明确说明函数类型:
def getObjectFromNullableOption[T](opt: Option[T]): T =
Option(opt).flatMap(identity).getOrElse(null.asInstanceOf[T])
我不完全确定具体细节,但我认为问题在于,在使用 java.util.Optional
时,您正在将 Scala Function
传递给 Optional.flatMap
,这需要Java Function
。 Scala 编译器可以自动为您转换它,但显然您必须具体明确类型才能使其工作,至少在这种情况下是这样。
关于您的原始代码的注释:您要求 T
成为 Null
的超类型,但这不是必需的。
关于您正在做的事情,您有更好的上下文,但作为一般建议,通常最好尽可能避免 null
Scala 代码中的泄漏。
我在java
中有如下方法protected <T> T getObjectFromNullableOptional(final Optional<T> opt) {
return Optional.ofNullable(opt).flatMap(innerOptional -> innerOptional).orElse(null);
}
它需要一个 java Optional
,它本身可以是 null
(我知道,这真的很糟糕,我们最终会解决这个问题)。它用另一个 Optional
包裹它,所以它变成 Some(Optional<T>)
或 None
。然后是flatMapped
,所以我们得到Optional<T>
或None
,最后应用orElse()
得到T
或null
。
如何在 Scala 中使用相同的 java.util.Optional 编写相同的方法?
protected def getObjectFromNullableOptional[T >: Null](opt : Optional[T]): T =
???
我试过了
protected def getObjectFromNullableOptional[T >: Null](opt : Optional[T]): T =
Optional.ofNullable(opt).flatMap(o => o).orElse(null)
但这给了我一个 Type mismatch
错误
Required: Function[_ >: Optional[T], Optional[NotInferedU]]
Found: Nothing => Nothing
我试过了
protected def getObjectFromNullableOptional[T >: Null](opt : Optional[T]): T =
Option(opt).flatMap(o => o).getOrElse(null)
但这给了我
Cannot resolve overloaded method 'flatMap'
编辑 我忘了说我使用的是 scala 2.11。我相信@tefanobaghino 的解决方案适用于 scala 2.13,但它引导我走向正确的道路。我把我的最终解决方案放在这个解决方案下面的评论中
最后一个错误引起了一些怀疑:看起来你在 Scala Option
中包装了 Java Optional
。相反,我本来希望这会失败,因为你试图 flatMap
到不同的类型,比如
error: type mismatch;
found : java.util.Optional[T] => java.util.Optional[T]
required: java.util.Optional[T] => Option[?]
这似乎可以满足您的要求:
import java.util.Optional
def getObjectFromNullableOptional[T](opt: Optional[T]): T =
Optional.ofNullable(opt).orElse(Optional.empty).orElse(null.asInstanceOf[T])
assert(getObjectFromNullableOptional(null) == null)
assert(getObjectFromNullableOptional(Optional.empty) == null)
assert(getObjectFromNullableOptional(Optional.of(1)) == 1)
你可以玩这个here on Scastie。
请注意,asInstanceOf
被编译为强制转换,而不是实际的方法调用,因此此代码不会抛出 NullPointerException
。
您还可以通过稍微帮助 Scala 的类型推断来更接近您的原始解决方案:
def getObjectFromNullableOptional[T](opt: Optional[T]): T =
Optional.ofNullable(opt).flatMap((o: Optional[T]) => o).orElse(null.asInstanceOf[T])
或者使用 Scala 的 identity
:
def getObjectFromNullableOptional[T](opt: Optional[T]): T =
Optional.ofNullable(opt).flatMap(identity[Optional[T]]).orElse(null.asInstanceOf[T])
对于使用 Scala 的解决方案 Option
你可以做一些非常接近的事情:
def getObjectFromNullableOption[T](opt: Option[T]): T =
Option(opt).getOrElse(None).getOrElse(null.asInstanceOf[T])
请注意,使用 Scala 的 Option
转到您的 flatMap
解决方案可以避免必须明确说明函数类型:
def getObjectFromNullableOption[T](opt: Option[T]): T =
Option(opt).flatMap(identity).getOrElse(null.asInstanceOf[T])
我不完全确定具体细节,但我认为问题在于,在使用 java.util.Optional
时,您正在将 Scala Function
传递给 Optional.flatMap
,这需要Java Function
。 Scala 编译器可以自动为您转换它,但显然您必须具体明确类型才能使其工作,至少在这种情况下是这样。
关于您的原始代码的注释:您要求 T
成为 Null
的超类型,但这不是必需的。
关于您正在做的事情,您有更好的上下文,但作为一般建议,通常最好尽可能避免 null
Scala 代码中的泄漏。