Type Erasure in Scala


Scala has a really strong type system. Scala’s static type system is listed as one of its strong points.

But even though Scala’s type system is theoretically very strong, in practice some type-related features are weakened by the restrictions and limitations of its runtime environment, i.e. Type Erasure.

So, what is type erasure?

Type erasure refers to the runtime encoding of parameterized classes in Scala. It is simply performed by Scala compiler in which it removes all the generic type information after compilation.

In Scala, generics are erased at runtime, which means that the runtime type of List[Int] and List[Boolean] is actually the same. 

Now the question arises is why the compiler does so?

It is so because Scala was defined with Type Erasure as the Java Virtual Machine (JVM) did not get generics. Java didn’t support generics from the beginning. So keeping backward compatibility in mind, Type Erasure was defined in Java SE version 5.0 to allow seamless interfacing with old, non-generic legacy code.

What happens under the hood is that type parameter in a generic class are replaced either with Object or its upper bound. This means that, at runtime, only the class exists, not its type parameters.

def determineListType[T](list: List[T]): Unit = list match {
case intList: List[Int] => println(s"List of integers: $intList")
case strList: List[String] => println(s"List of Strings: $strList")
}

In the example, JVM knows it is handling a, scala.collection.immutable.List but not that this list is parameterized with which dataType. The above code snippet compile successfully, but when you run it, it will give the following warning:

The reason for the warning is that the runtime has no idea about the actual class that a generic class was parameterized with.

So, the question is how to deal with type erasure in Scala?

Scala introduced Manifests somewhere around version 2.7. However, they had problems with not being able to represent certain types so Scala 2.10. deprecated them in favor of the more powerful TypeTags.

Type tags are divided into three separate types:

  • ClassTag
  • TypeTag
  • WeakTypeTag

ClassTag:

ClassTag[T] stores the erased class of a given type,T accessible via the runtime Class field. ClassTags are a weaker special case of scala.reflect.api.TypeTags#TypeTags, in that they wrap only the runtime class of a given type, whereas a TypeTag contains all static type information. That is, ClassTags are constructed from knowing only the top-level class of a type, without necessarily knowing all of its argument types.

This is particularly useful for instantiating generic Arrays whose element types are unknown at compile time.

For example,

def createArr[A: ClassTag](seq: A*) = Array[A](seq: _*)

ClassTag provides only the information needed to create types at runtime. If we ask for runtime class of List[Int], we can see that information about Int that the list is parameterized with is lost i.e. they don’t care about type erasure.

import scala.reflect._
scala>classTag[List[Int]].runtimeClass
res0: Class[_] = class scala.collection.immutable.List

TypeTag:

If one wants “full” types, TypeTags should be used:

import scala.reflect.runtime.universe._
scala> typeTag[List[Int]].tpe
res9: reflect.runtime.universe.Type = scala.List[Int]

method tpe of TypeTag results in a full type

The primary use case of TypeTag is to give access to erased types. Scala’s TypeTags can give us details about type parameters that the Java compiler would normally erase.

WeakTypeTag:

WeakTypeTag[T] generalizes TypeTag[T]. TypeTag represents a concrete type which means it just allows fully instantiated types whereas WeakTypeTag allows any type.

import scala.reflect.runtime.universe._
def determinType[T] = typeTag[T]
determinType[Int]

It will give the following error:

But, if I use weakTypeTag, it will run fine

 import scala.reflect.runtime.universe._
 def determinType[T] = typeTag[T] determinType[Int] 

 

Please feel free to suggest or comment. Happy blogging 😉

References:

1. Scala in depth

2. Scala documentation


knoldus-advt-sticker


This entry was posted in Scala and tagged , , . Bookmark the permalink.

3 Responses to Type Erasure in Scala

  1. not me says:

    To be honest, this blog post feels very incomplete. Ok, there are 3 different TypeTags. You say a few words about the difference, but you use the same example. My conclusion is that you can use whichever you want from the 3 possibilities? Can you extend with examples where you should use one of them instead of the others?

    ClassTags are a weaker special case of scala.reflect.api.TypeTags#TypeTags, in that they wrap only the runtime class of a given type, whereas a TypeTag contains all static type information. That is, ClassTags are constructed from knowing only the top-level class of a type, without necessarily knowing all of its argument types.

    well, if I know the difference from reading this sentence, then I probably wouldn’t need to open this blog post…

  2. Thanks for the feedback. I have updated the blog with different examples for different Tags.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s