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.
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[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.
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.
If one wants “full” types, TypeTags should be used:
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.
TypeTag[T]. TypeTag represents a concrete type which means it just allows fully instantiated types whereas WeakTypeTag allows any type.
It will give the following error:
But, if I use weakTypeTag, it will run fine
Please feel free to suggest or comment. Happy blogging 😉