scala中的@specialized
Posted 刀哥的学习园地
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala中的@specialized相关的知识,希望对你有一定的参考价值。
scala中的@specialized
为什么需要@specialized
@specialized
是为了解决由于泛型擦除而需要对基础数据类型进行装箱/拆箱操作所带来的性能问题
@specialized
从 scala2.8
开始加入的,为什么要增加呢?
Java/Jvm的泛型是类型擦除的,也就是说泛型编译时会被丢弃,全部向上转型为 Object
, 因此对基础数据类型(primitive
) 来说, 无法直接使用基础数据类型
作为泛型参数,如 List<int>
是不可以的,所以就有了 Box
和 Unbox
, 将 int
装箱为 Integer
, double
装箱为 Double
, 等等。
带来的问题是内存的增加, double
本身只需要 8 个字节,装箱为 Double
后,将需要 24 个字节,对于一些有庞大集合的应用来说,很可能会带来内存的
性能瓶颈。
Scala由于需要编译为Java字节码,因此也就继承了Java/JVM这个缺陷,为了改进这个缺陷,Scala增加了 @specialized
注解,来指示Scala编译器来规避这个问题
@specialized 是如何解决的
首先,Scala语言标准库中定义了 specialized
来告知编译器针对泛型进行优化:
class specialized(group: SpecializedGroup) extends
scala.annotation.StaticAnnotation {
def this(types: Specializable*) = this(new Group(types.toList)) def this() = this(Primitives)
}
其次,针对设置了 @specialized
的泛型类型,Scala编译器会针对特定的基础数据类型生成特定版本的代码,例如:
import scala.{specialized => sp}
trait Eq[@sp(Int) T] extends Any with Serializable {self =>
def eqv(x: T, y: T): Boolean
}
用 scalac -print
进行编译便可看见结果,如果 @sp
不指定类型,则会生成所有基础数据类型的特定版本。
需要注意的问题
固然 @specialized
通过特化版本的方式能够提高性能,但也是有缺点的:
1. 会产生大量的特化版本的类,导致运行时需要加载更多的类型
2. 如果有泛型依赖,被依赖中的泛型没有设置 specialized
就算设置了,也不会被特化,因此有一定的局限性
参考资料
Specializing for primitive types http://www.scala-notes.org/2011/04/specializing-for-primitive-types/
Specialization - Dragos http://days2010.scala-lang.org/node/138/151/
以上是关于scala中的@specialized的主要内容,如果未能解决你的问题,请参考以下文章