当使用新的Scala 3的标志-Yexplicit-nulls
时,每个没有显式非null注释的Java代码都被视为可为null,因此每个没有返回基元类型T
的Java方法都有效地返回T | Null
。
问题:在Scala中,String只是java.lang.String
的别名。由于核心Java不包含任何关于可为null的注释,Scala3将String方法的返回类型视为可为null。
示例:(通过Scala REPL/sbt控制台和Gradle尝试(
scala> val bla: String = null // check whether the compiler option is turned on
-- Error:
1 |val bla: String = null
| ^^^^
| Found: Null
| Required: String
scala> val bla: String = "hey"
val bla: String = hey
scala> bla.split("e")
val res0: Array[String | Null] | Null = Array(h, y)
返回类型Array[String | Null] | Null
完全是疯狂的。split
方法的约定显然是给定的,因为它总是返回一个数组,并且该数组总是包含至少一个字符串(并且没有一个字符串为null(。
这真的是可悲的现实吗,还是我做错了什么
为了使上述工作,我总是要写:
"hey".split("e").nn.map(_.nn) // this would finally give me just Array[String]
我发现了一个bug报告,它实际上与我最初在这里询问的内容相同。Dotty/Scala3团队似乎认为这是";不是bug";。
有人建议使用unsafeNulls标志。这更像是一个";让我们禁用我们刚刚启用的功能;。
这里有一个实验语言特性unsafeJavaReturn
,它假设Java方法不会在显式null 中返回可为null的值
https://github.com/lampepfl/dotty/pull/15096
这比unsafeNulls
攻击性小,因为它只在一定范围内影响Java互操作。