关于 如何测试数组空虚的问题(def unique(objects):
return list(sorted(set(objects)))
做得很好)。相反,我的问题是,为什么
arr.length == 0
工作和
scala> Array().isEmpty
res1: Boolean = true
工作,但
scala> val x = Array[String]()
x: Array[String] = Array()
scala> x.isEmpty
res2: Boolean = true
没有?
答案 0 :(得分:4)
正如@MichaelZajac指出的那样,Nothing
是一切的子类型(其对应Any
是一切的超类型)。特别是它也是AnyRef
的子类型。事实上,有一个更普遍的genericArrayOps
没有任何类型约束(例如Array[Any]().isEmpty
工作)!允许您使用isEmpty
的隐式转换应启动,但当然不会,即使显式调用转换也没问题。
link @slouc给出了答案,即Scala编译器在进行隐式解析时以特殊方式处理Nothing
,因为Nothing
是类型的默认下界进行类型推断。
现在为什么Nothing
不能在隐式解决方案中考虑到它?那么关于Nothing
的棘手问题是它是一切的子类型。这意味着如果Scala在任何时候推断类型为Nothing
,则每个隐式转换都会立即生效。这可能会隐藏类型错误(您永远不应该有Nothing
的实例,但是当Nothing
成为Int
时......那么谁呢?)。 (注意我会喜欢那些真正攻击编译器的人跳入并确认/否认/详细说明这一点)
答案 1 :(得分:1)
编辑:可能这个答案不正确。但我在这里保守,以示我是如何尝试调查此问题的。对我而言,它看起来像是编译器中的一个错误。
答案是Array[T <: AnyRef]
存在的隐式转换
字符串为AnyRef
,Nothing
不是AnyRef
。
你怎么能自己发现这个?
在IntelliJ中,您可以在isEmpty
下看到灰色下划线
这意味着方法isEmpty
不是Array的方法,而是隐式(在类中具有隐式转换的类的方法)。
所以当你按照它时,你会在源代码中找到这一行 -
implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs)
这解释了当T扩展AnyRef
时隐式转换在Array [T]上 回到我们的案例 -
String <: AnyRef
,但这不适用于Nothing