【发布时间】:2019-04-25 09:20:30
【问题描述】:
从 this scheme 在 Scala 之旅中的 Unified typed 文章中,我认为 AnyRef 和 Object 是完全等价的。
但是,在 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
因此,至少在某些级别的类型信息Object 和AnyRef 是有些区别的。它是做什么用的?还是纯粹是个bug?
【问题讨论】:
-
TypeTag和ClassTag只是提供两个不同的东西。请参阅stackoverflow.com/questions/40202504/… 和medium.com/@sinisalouc/… 您可能看到TypeTag是AnyRef和Object之间的实际区别,因为TypeTag处理类型并且AnyRef确实不同于Object类型明智的,因为AnyRef只是一个trait并且确实不同于AnyRefgithub.com/scala/scala/tree/2.12.x/src/library-aux/scala -
请注意,您不需要
getTypeTag,您可以只写例如implicitly[TypeTag[AnyRef]]召唤一个实例。 -
@DanielHinojosa,有趣的是
AnyRef被声明为特征。但我不认为这真的是一个特征,我认为一些编译器魔法以不同的方式处理标准库中的这些核心内容。首先,我相信Seth Tissue's opinion;第二,我可以new AnyRef(),但不能trait T; new T();第三,typeTag.mirror.runtimeClass(typeTag.tpe).isInterface()为AnyRef返回false(通常它为特征返回true)。 -
@Sasha 这是一个有趣的问题,我认为之前的自述文件会带来一些答案。 github.com/scala/scala/blob/2.12.x/src/library-aux/README。 “此目录下的源文件无法通过正常方式编译。它们存在用于引导和文档目的。”因此,在 scala 引导过程中有些东西会采用 AnyRef 的特性并在运行时(可能)将其与
java.lang.Object合并,但TypeTags的AnyRef和Object是不同的。现在,bootstrap 发生了什么?