这在 Java 中从来都不是问题,因为它不支持泛型中的原始类型。因此,以下代码在 Java 中是相当合法的:
public static <T> void f(T t){out.println("normal type");}
public static <T> void f(T[] a){out.println("Array type");}
另一方面,Scala 支持所有类型的泛型。尽管 Scala 语言没有原语,但生成的字节码将它们用于 Int、Float、Char 和 Boolean 等类型。它使 Java 代码和 Scala 代码有所不同。Java 代码不接受int[]
作为数组,因为int
它不是java.lang.Object
. 所以Java可以将这些方法参数类型擦除为Object
和Object[]
。(这意味着在 JVM 上。Ljava/lang/Object;
)[Ljava/lang/Object;
另一方面,您的 Scala 代码处理所有数组,包括Array[Int]
、Array[Float]
、Array[Char]
等Array[Boolean]
。这些数组是(或可以是)原始类型的数组。它们不能被强制转换到JVM 级别Array[Object]
或Array[anything else]
在 JVM 级别上。Array[Int]
和有一个超类型Array[Char]
:它是java.lang.Object
。它是您可能希望拥有的更通用的超类型。
为了支持这些陈述,我编写了一个不太通用的方法 f 的代码:
def f[T](t: T) = println("normal type")
def f[T <: AnyRef](a: Array[T]) = println("Array type")
此变体的工作方式类似于 Java 代码。这意味着,不支持原语数组。但是这个小改动足以让它编译。另一方面,由于类型擦除的原因,无法编译以下代码:
def f[T](t: T) = println("normal type")
def f[T <: AnyVal](a: Array[T]) = println("Array type")
添加@specialized 并不能解决问题,因为生成了一个泛型方法:
def f[T](t: T) = println("normal type")
def f[@specialized T <: AnyVal](a: Array[T]) = println("Array type")
我希望@specialized 可能已经解决了这个问题(在某些情况下),但编译器目前不支持它。但我不认为这将是 scalac 的高优先级增强。