Scala:数组和类型删除

标签 scala type-erasure overloading

我想编写如下重载函数:

case class A[T](t: T)
def f[T](t: T) = println("normal type")
def f[T](a: A[T]) = println("A type")

结果正如我所料:

f(5)       => normal type
f(A(5))  => A type



到现在为止还挺好。但问题是同样的事情不适用于数组:
def f[T](t: T) = println("normal type")
def f[T](a: Array[T]) = println("Array type")

现在编译器提示:

double definition: method f:[T](t: Array[T])Unit and method f:[T](t: T)Unit at line 14 have same type after erasure: (t: java.lang.Object)Unit



我认为类型删除后的第二个函数的签名应该是 (a: Array[Object])Unit 而不是 (t: Object)Unit,所以它们不应该相互冲突。我在这里缺少什么?

如果我做错了什么,写 f 的正确方法是什么,以便根据参数的类型调用正确的方法?

最佳答案

这在 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可以将这些方法参数类型删除到ObjectObject[] . (这意味着 Ljava/lang/Object;[Ljava/lang/Object; 在 JVM 上。)

另一方面,您的 Scala 代码处理所有数组,包括 Array[Int] , Array[Float] , Array[Char] , Array[Boolean]等等。这些数组是(或可以是)原始类型的数组。它们不能被强制转换为 Array[Object]Array[anything else]在 JVM 级别。 Array[Int]只有一个父类(super class)型和 Array[Char] : 是java.lang.Object .这是您可能希望拥有的更一般的父类(super class)型。

为了支持这些陈述,我编写了一个使用较少通用方法 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 的高优先级增强。

关于Scala:数组和类型删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14355092/

相关文章:

java 。重载方法

function - 在 Julia 中定义一个继承自向量的类型

java - 收集参数以应用于 Java/Scala 中的柯里化(Currying)函数

scala - 在 Scala 中绑定(bind)类型之后的另一个子类型

scala - 为什么 Scala 的类型推断器会因这组涉及参数化类型的隐式参数而失败?

Java 泛型 : Why does my @SuppressWarnings ("unchecked") work in this case, 而不是其他?

java - 是否有理由不能拥有具有相同签名的静态和非静态方法?

scala - 更改 sbt 任务中的设置

java - android 小部件 SearchView OnQueryTextListener

java - 用户定义泛型类的 Spring TypeDescriptor