为什么数组需要ClassTag,而List这样的集合却不需要? [英] Why do Arrays require ClassTags but collections like List do not?

查看:50
本文介绍了为什么数组需要ClassTag,而List这样的集合却不需要?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这很好:

def x[A](a: A) = List(a)

没有适用于A的ClassTag:

No ClassTag available for A:

def y[A](a: A) = Array(a)

但是当然,这是犹太洁食:

But of course this is kosher:

def y[A : ClassTag](a: A) = Array(a)

有什么用?

推荐答案

数组在运行时保留其类型,但由于类型擦除,泛型方法在运行时会失去其泛型。因此,如果您要在运行时通过通用方法动态创建数组,则必须保留通用类型信息。 JVM由于擦除而无法识别类型,但是Scala会以ClassTag的形式保留信息,从而可以避免擦除问题。

Arrays preserve their type at runtime, but generic methods lose their genericity at runtime due to type erasure. So, if you're dynamically creating an array at runtime from a generic method, the generic type information has to be preserved. The JVM is not aware of the type due to erasure, but Scala keeps the information around in the form of the ClassTag, allowing you to avoid the erasure problem.

您可以通过Java反射来作弊

You could cheat by using Java reflection

def y[A](a: A, length: Int) = java.lang.reflect.Array.newInstance(a.getClass, length)

但这将是可怕的-请注意,由于擦除,返回的类型是Object而不是Array [A]

but this would be terrible - note that the returned type is Object, not Array[A], due to erasure

scala> y("foo", 1)
res2: Object = Array(null)

也请注意,java.lang.reflect.Array.newInstance()返回 API文档

Also note that java.lang.reflect.Array.newInstance() returns Object in the API documentation.

这是有道理的,因为Java具有擦除功能,并且没有ClassTag。

This makes sense because Java has erasure and doesn't have ClassTags.

Scala具有ClassTag,因此可以使用适当的类型创建在运行时创建的数组:

Scala has ClassTags, so the array created at runtime can be created with the appropriate type:

scala> def y[A : ClassTag](a: A) = Array(a)
y: [A](a: A)(implicit evidence$1: scala.reflect.ClassTag[A])Array[A]

scala> y("foo")
res4: Array[String] = Array(foo)

scala> y(1)
res5: Array[Int] = Array(1)

了解更多关于JVM上的类型擦除的信息(Java示例):

Learn more about type erasure on the JVM here (Java examples):

  • Erasure of generic types
  • Erasure of generic methods
  • Erasure of bridge methods
  • Non-reifiable types

当然,由于擦除,A的列表在运行时变为AnyRef的列表,因此,只要在编译时(通过泛型)验证了类型检查,JVM就不会在运行时关心什么类型实例化通用对象时。

Of course, due to erasure, List of A becomes List of AnyRef at runtime, so as long as the type checking is validated at compile time (via generics), the JVM doesn't care at runtime what the types are when the generic object is instantiated.

这篇关于为什么数组需要ClassTag,而List这样的集合却不需要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆