如何在 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()得到Tnull

如何在 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 的超类型,但这不是必需的。

关于您正在做的事情,您有更好的上下文,但作为一般建议,通常最好尽可能避免 nullScala 代码中的泄漏。