problem
在 scala 中,type parameter 可以为 primitive type,比如Int
, Long
, Float
, Double
...
但由于 JVM 的类型擦除,List[Int]
在运行时仍会被转化为List[Object]
即基础类型需要被装箱到某个wrapper class
中
@specialized
可以在声明type parameter时,针对一些 type 使用@specialized
annotation
import scala.{specialized => sp}
class Wrapper[@sp(Short, Int, Long, Float, Double) A](unwrap: A)
new Wrapper[Short](42)
res0: Wrapper[Short] = Wrapper$mcS$sp@2f657dc7
new Wrapper[Int](42)
res1: Wrapper[Int] = Wrapper$mcI$sp@213b4ebf
new Wrapper[Long](42L)
res2: Wrapper[Long] = Wrapper$mcJ$sp@600f799c
new Wrapper[Float](3.14f)
res3: Wrapper[Float] = Wrapper$mcF$sp@5b6b6cb0
new Wrapper[Double](3.14)
res4: Wrapper[Double] = Wrapper$mcD$sp@465ebfb9
new Wrapper[String]("hi")
res5: Wrapper[String] = Wrapper@7ee6425d
可以看到,编译器会针对所声明的5个基础类型和1个泛型,编译出6个不同版本的Wrapper
.
这样,对于specialized
的类型,就可以避免运行时boxing
和unboxing
开销。
syntax
-
class
的 specialization 会应用于所有使用了其 type parameter 的 members - 可以针对
class
和member
分别设置spacialization
// class Vector specialized all primitive types
class Vector[@specialized A] {
def apply(i: Int): A = //..
// method map only specialized Int and Boolean
def map[@specialized(Int, Boolean) B](f: A => B) =
//..
}