Scala中对象和AnyRef之间的区别

时间:2018-11-22 16:41:11

标签: scala types

在Scala之旅的this scheme文章的Unified typed中,我认为AnyRefObject是完全等效的。

但是,在Eclipse中检查声明时,我发现了一些有趣的东西:

object ClassTag {
  …
  val Object  : ClassTag[java.lang.Object] = Manifest.Object
  …
  val AnyRef  : ClassTag[scala.AnyRef]     = Manifest.AnyRef
  …
}

object TypeTag {
  …
  val AnyRef:  TypeTag[scala.AnyRef]     = new PredefTypeTag[scala.AnyRef]     (AnyRefTpe,  _.TypeTag.AnyRef)
  val Object:  TypeTag[java.lang.Object] = new PredefTypeTag[java.lang.Object] (ObjectTpe,  _.TypeTag.Object)
  …
}

一些实验:

import scala.reflect.ClassTag
import scala.reflect.runtime.universe.TypeTag

println(ClassTag.AnyRef == ClassTag.Object) //true
def getClassTag[V](v: V)(implicit tag: ClassTag[V]) = tag
println(getClassTag[AnyRef](null)) //Object
println(getClassTag[Object](null)) //Object
println(getClassTag(null.asInstanceOf[AnyRef])) //Object
println(getClassTag(null.asInstanceOf[Object])) //Object
println(getClassTag(new AnyRef())) //Object
println(getClassTag(new Object())) //Object
println
println(TypeTag.AnyRef == TypeTag.Object) //false
def getTypeTag[V](v: V)(implicit tag: TypeTag[V]) = tag
println(getTypeTag[AnyRef](null)) //TypeTag[AnyRef]
println(getTypeTag[Object](null)) //TypeTag[Object]
println(getTypeTag(null.asInstanceOf[AnyRef])) //TypeTag[AnyRef]
println(getTypeTag(null.asInstanceOf[Object])) //TypeTag[Object]
println(getTypeTag(new AnyRef())) //TypeTag[Object]
println(getTypeTag(new Object())) //TypeTag[Object]
println(getTypeTag(new AnyRef().asInstanceOf[AnyRef])) //TypeTag[AnyRef]
println(getTypeTag(new AnyRef().asInstanceOf[Object])) //TypeTag[Object]
println(getTypeTag(new Object().asInstanceOf[AnyRef])) //TypeTag[AnyRef]
println(getTypeTag(new Object().asInstanceOf[Object])) //TypeTag[Object]
println
println(TypeTag.AnyRef.tpe == TypeTag.Object.tpe) //false
def getType[V](v: V)(implicit tag: TypeTag[V]) = tag.tpe
println(getType[AnyRef](null)) //AnyRef
println(getType[Object](null)) //Object
println(getType(null.asInstanceOf[AnyRef])) //AnyRef
println(getType(null.asInstanceOf[Object])) //Object
println(getType(new AnyRef())) //Object
println(getType(new Object())) //Object
println(getType(new AnyRef().asInstanceOf[AnyRef])) //AnyRef
println(getType(new AnyRef().asInstanceOf[Object])) //Object
println(getType(new Object().asInstanceOf[AnyRef])) //AnyRef
println(getType(new Object().asInstanceOf[Object])) //Object

因此,至少在某些级别的类型信息ObjectAnyRef有所区别。它是做什么的?还是纯粹是一个错误?

1 个答案:

答案 0 :(得分:5)

您会在任何类型的别名中看到类似的行为,我认为上面的示例中Object / AnyRef并没有什么特别之处。

scala 2.12.7> import scala.reflect.runtime.universe.TypeTag
import scala.reflect.runtime.universe.TypeTag

scala 2.12.7> class C; type D = C
defined class C
defined type alias D

scala 2.12.7> implicitly[TypeTag[C]]
res0: reflect.runtime.universe.TypeTag[C] = TypeTag[C]

scala 2.12.7> implicitly[TypeTag[D]]
res1: reflect.runtime.universe.TypeTag[D] = TypeTag[D]

CD是不同但“等效”的类型。请参见SLS 3.5,“类型之间的关系”(https://www.scala-lang.org/files/archive/spec/2.12/03-types.html#relations-between-types