Specializing for primitive types

 

 

    转之http://www.scala-notes.org/2011/04/specializing-for-primitive-types/

 

One interesting feature that was added to Scala in version 2.8 is specialization, using the @specialized annotation. First, a little background information.

Generics in Java and the JVM, and consequently also in Scala, are implemented by using type erasure. That means that if you have an instance of a generic class, for example List[String], then the compiler will throw away the information about the type argument, so that at runtime it will look like List[Object].

In Java, primitive types are treated very differently from reference types. One of the things that you cannot do in Java is use primitive types to fill in type parameters – for example, you cannot make a List<int>. If you want to create a list that holds integers, you’ll have to use the wrapper class Integer. A drawback of this approach is that you need to box each of your primitive ints into an Integer object that takes up a lot more memory. I’ve done some tests and found that on my JVM a double only takes up 8 bytes, but a Double object takes up 24 bytes. Also, the boxing and unboxing takes up processor time, which can become a serious bottleneck if you’re dealing with large collections of numbers.

In Scala, the distinction between primitive types and reference types is far less great than in Java, and you can use types like Int directly for type arguments. But a List[Int] is still converted to a List[Object] at runtime because of type erasure and since primitive types are not subclasses of Object on the JVM, Scala will still box the Ints to objects of some wrapper class – which makes a List[Int] in Scala just as inefficient as aList<Integer> in Java.

The @specialized annotation and compiler support are meant to get rid of this inefficiency. Iulian Dragos explains it very clearly in this video. If you create a generic class and you use the @specialized annotation, for example like this:

1 class Container[@specialized(Int) T](value: T) {
2   def apply(): = value
3 }

the compiler will actually generate two versions of the class: the normal, generic one, in which the type parameter is erased, and a special subclass that uses the primitive type Int, without the need to box or unbox the value. You can see this when you compile the code using the -print option of the compiler:

01 jesper@jesper-desktop:~/Projects/boxing$ scalac -print Container.scala
02 [[syntax trees at end of cleanup]]// Scala source: Container.scala
分享到:
评论
ordinary
  • 浏览: 32626 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
border-top-width: 0px !important; border-right-width: 0px !important; border-bottom-width: 0px !important; border-left-width: 0px !important; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; font-size: 12px !important; margin-top: 0px !important; margin-ri

你可能感兴趣的:(jvm,scala,UP)