我正在尝试生成package object
中定义的类的运行时类名称。
示例:
package com.foo
package object bar {
case class MyCaseClass()
}
import bar._
MyCaseClass().getClass.getCanonicalName
以上内容将生成com.foo.bar.package.MyCaseClass
如果我使用WeakTypeTag
,它将正确生成类型为com.foo.bar.MyCaseClass
。
package com.foo
trait MyTrait
case class MyImpl extends MyTrait
def getType[T](t: T)(implicit weakTypeTag WeakTypeTag[T]): String = {
weakTypeTag.tpe.fullName
}
上述行为差异的原因是什么?我知道我一定缺少有关Scala类型系统的东西...
答案 0 :(得分:3)
这与类型系统无关,而与JVM上包对象的编码无关。例如,JVM没有包级方法,因此Scala编译器必须创建一个综合类,该类具有与包对象中的定义相对应的静态方法,内部类等。该类的名称为package
,是一个任意但不言自明的名称,它的优点是在Scala和Java中都是关键字,因此不太可能导致与非合成代码的冲突。
Java的反射API对Scala一无所知,因此自然无法向您隐藏此编码。调用getClass.getCanonicalName
时,您会看到实际的类名称,该名称与编译代码时在com/foo/bar/package\$MyCaseClass.class
上找到的类文件相对应。
Scala的反射API确实了解Scala的封装对象编码,它们将向您隐藏合成的package
类。可以说这是有道理的,因为编码的细节不在规范中(如果我没记错的话?),并且在平台或语言版本等方面可能有所不同。
差异有点令人困惑,但这不是您唯一遇到分歧的地方-Scala反射API隐藏了Java反射无法做到的许多改头换面等。