可以在 Scala 中找到参数类型方法 return 类型,其中参数是原始类型吗?

Possible to find parameter type methods return type in Scala where parameter is a primitive type?

假设我有:

class X
{
   val listPrimitive: List[Int] = null
   val listX: List[X] = null
}

然后我打印出 Scala 中每个方法的 return 类型如下:

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

注意。由于 JVM 类型擦除,这似乎不是问题,因为我 可以 找到 List 的类型参数。看起来 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 中可用,这样才能正确地编译失败​​。

更新 2:

假设您正在为 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[_],我可以确定其方法的 return 类型的 TypeTokens 吗?显然这是可能的,因为此信息必须包含(某处)在 .class 文件中,以便 scala 编译器正确生成类型不匹配错误(见上文)。

在 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[_] 对象。如果需要,您可以通过 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)

我想如果你真的只有class,你可以创建一个只加载class的class加载器?不过,我无法想象没有 class 甚至没有值的用例。