Scala中Object和AnyRef之间的区别

Sas*_*sha 4 types scala

从Scala之旅的统一类型文章中的这个方案我认为并且是完全等价的.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)
  …
}
Run Code Online (Sandbox Code Playgroud)

一些实验:

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
Run Code Online (Sandbox Code Playgroud)

所以,至少在某些级别的类型信息中Object并且AnyRef有所区别.它做了什么?或者它纯粹是一个错误?

Set*_*sue 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]
Run Code Online (Sandbox Code Playgroud)

C并且D是不同但"等同"的类型.参见SLS 3.5,"类型之间的关系"(https://www.scala-lang.org/files/archive/spec/2.12/03-types.html#relations-between-types)