如何将可以为null的值或数组隐式包装到Scala选项中

如何将可以为null的值或数组隐式包装到Scala选项中,scala,null,option,implicit-conversion,implicit,Scala,Null,Option,Implicit Conversion,Implicit,我将这个Java类作为Scala程序(如Axis Jar)的依赖项包含在Jar文件中: 在我的Scala程序中,我有一个Java API,它将MyClass的实例MyClass的实例返回到我的Scala程序中: val myInstance = JavaAPI.getInstanceOfMyClass() 然后我尝试在Scala程序中使用SomeString数组,但它是null(假设它没有正确初始化) 因此,当我这样做时: for(str <- myInstance.getSomeStr

我将这个Java类作为Scala程序(如Axis Jar)的依赖项包含在Jar文件中:

在我的Scala程序中,我有一个Java API,它将MyClass的实例MyClass的实例返回到我的Scala程序中:

val myInstance = JavaAPI.getInstanceOfMyClass()
然后我尝试在Scala程序中使用SomeString数组,但它是null(假设它没有正确初始化)

因此,当我这样做时:

for(str <- myInstance.getSomeStrings())
for(str编辑:

map
以及
flatMap
始终必须返回调用它们的相同类型。如果您有一个列表,您将始终从
map
返回一个列表。对于一个选项也是如此。如果您尝试在一个flatMap中混合两种类型,这很可能不起作用。您应该怎么做

Some(Array(1,2)).flatMap { x => 
  x.map { _ * 2 }
}
返回?某些(2,4)是不可能的。因此您得到一个类型错误。因此,您必须执行嵌套的
map{map}
而不是
flatMap{map}

在您的情况下,其工作原理如下:

case class A(b: B)
case class B(c: String)

val result = for(as <- Option(Array(A(B("foo")), A(B("bar"))))) yield {
  for(a <- as; b <- Option(a.b); c <- Option(b.c)) yield {
    c
  }
}

val result=for(x
//用绳子做东西
}
}

由于类型推断,您不需要编写类型,也不需要
getOrElse
,因为映射不会为
None
执行。如果需要打开值,您只需对结果执行
getOrElse

我认为您的
getOrElse
版本没有那么糟糕(您可以在
选项
之后删除
[Array[String]]
使其略短一些,因为这是可以推断出来的)。如果您想要更简洁的内容,请使用以下方法:

for (str <- Option(myInstance.getSomeStrings).flatten) ...
请注意,此处不能使用
yield
,原因是drexin在下面的注释中突出显示

或者您可以
MyClass

implicit def withNullWrapper(c: MyClass) = new {
  def getSomeStringsOrNot() = Option(c.getSomeStrings).getOrElse(Array[String]())
}

for (str <- myInstance.getSomeStringsOrNot) ...
implicit def with nullwrapper(c:MyClass)=新建{
def getSomeStringsOrNot()=选项(c.getSomeStrings).getOrElse(数组[String]())
}

对于(str简单规则:如果有
null
,则将其设置为
选项
。因此:

for {
  array <- Option(myInstance.getSomeStrings)
  element <- array
  thingy <- Option(element.method)
} yield thingy

请注意,第二个
选项
无需触摸:导致问题的是第一个生成器。
选项
除第一个生成器以外的任何地方都不是问题。

谢谢。我应该更好地解释我自己。问题是当您在for-like-for中有“嵌套”作业时(a您的flatMap示例将不起作用,因为它不遵循monad定律。strings是数组[String]因此,这里不能使用flatMap。你是对的,但是对于
,同样的
-如果你不使用
产生
,理解语法将起作用。是的,因为它将被转换为嵌套的
foreach
。但是,你依赖于应该避免的副作用。你应该指定“链接的可空部分结果”问题中的要求。
case class A(b: B)
case class B(c: String)

val result = for(as <- Option(Array(A(B("foo")), A(B("bar"))))) yield {
  for(a <- as; b <- Option(a.b); c <- Option(b.c)) yield {
    c
  }
}
val result = Option(myInstance.getSomeStrings).map { x =>
  x.map { y =>
    // do stuff with strings
  }
}
val result = for(x <- Option(myInstance.getSomeStrings)) yield {
  x.map { y =>
    // do stuff with strings
  }
}
for (str <- Option(myInstance.getSomeStrings).flatten) ...
for {
  strings <- Option(myInstance.getSomeStrings)
  str <- strings
} ...
implicit def withNullWrapper(c: MyClass) = new {
  def getSomeStringsOrNot() = Option(c.getSomeStrings).getOrElse(Array[String]())
}

for (str <- myInstance.getSomeStringsOrNot) ...
for {
  array <- Option(myInstance.getSomeStrings)
  element <- array
  thingy <- Option(element.method)
} yield thingy
for {
  array <- Option(myInstance.getSomeStrings).toSeq
  element <- array
  thingy <- Option(element.method)
} yield thingy