假设我有:
class X
{
val listPrimitive: List[Int] = null
val listX: List[X] = null
}
我在Scala中打印出每个方法的返回类型,如下所示:
classOf[ComplexType].getMethods().foreach { m => println(s"${m.getName}: ${m.getGenericReturnType()}") }
listPrimitive: scala.collection.immutable.List<Object>
listX: scala.collection.immutable.List<X>
所以...我可以确定listX的元素类型是X,但有没有办法通过反射确定listPrimitive的元素类型实际上是java.lang.Integer? ...
val list:List[Int] = List[Int](123);
val listErased:List[_] = list;
println(s"${listErased(0).getClass()}") // java.lang.Integer
NB。这似乎不是由于JVM类型擦除的问题,因为我可以找到List的types参数。看起来scala编译器抛弃了这个类型信息IFF,参数类型是java.lang。[numbers]。
更新:
由于以下实验,我怀疑此类型信息 可用。假设我定义:
class TestX{
def f(x:X):Unit = {
val floats:List[Float] = x.listPrimitive() // type mismatch error
}
}
和X.class通过jar导入。完整类型信息必须在X.class中可用,以便正确地无法编译。
UPDATE2:
想象一下,您正在为Java序列化库编写scala扩展。你需要实现一个:
def getSerializer(clz:Class[_]):Serializer
根据是否需要执行不同操作的功能:
clz==List[Int] (or equivalently: List[java.lang.Integer])
clz==List[Float] (or equivalently: List[java.lang.Float])
clz==List[MyClass]
我的问题是我只会看到:
clz==List[Object]
clz==List[Object]
clz==List[MyClass]
因为clz是作为clz.getMethods()(i).getGenericReturnType()提供给这个函数的。
从clz开始:Class [_]如何恢复丢失的元素类型信息?
我不清楚TypeToken会帮助我,因为它的用法:
typeTag[T]
要求我提供T(即在编译时)。
所以,一个解决方案的路径......给定一些clz:Class [_],我可以确定其方法的返回类型的TypeTokens吗?显然,这是可能的,因为此信息必须包含在某个.class文件中(某处),以便scala编译器正确生成类型不匹配错误(参见上文)。
答案 0 :(得分:1)
在java字节码级别Int
必须表示为其他东西(显然是Object
),因为List
只能包含对象,而不能包含基元。这就是java级反射可以告诉你的。但是,正如您所推断的那样,scala类型信息存在(在字节码级别它是注释中的IIRC),因此您应该能够使用scala反射检查它:
import scala.reflect.runtime.universe._
val list:List[Int] = List[Int](123)
def printTypeOf[A: TypeTag](a: A) = println(typeOf[A])
printTypeOf(list)
对update2的响应:您应该使用scala反射来获取镜像,而不是Class[_]
对象。如果需要,您可以通过课程名称:
import scala.reflect.runtime.universe._
val rm = runtimeMirror(getClass.getClassLoader)
val someClass: Class[_] = ...
val scalaMirrorOfClass = rm.staticClass(someClass.getName)
// or possibly rm.reflectClass(someClass) ?
val someObject: Any = ...
val scalaMirrorOfObject = rm.reflectClass(someObject)
我想如果你真的只有这个类,你可以创建一个只加载该类的类加载器吗?我无法想象你不会拥有这个类,甚至是一个值的用例。