According to scala doc,TypeTag
contains more information than ClassTag
. It seems to me that TypeTag
can do more things than ClassTag
, like bring the type parameter information of compile time to runtime, etc.
However, the following example shows that ClassTag
can do the job, while the TypeTag
not. I want to understand why.
import scala.reflect.ClassTag
import scala.reflect.runtime.universe.TypeTag
// def func[T](o: Any): Unit = {
// def func[T : TypeTag](o: Any): Unit = {
def func[T : ClassTag](o: Any): Unit = {
o match {
case x: T => println(Some(x))
case _ => println(None)
}spark
}
func[Map[Int, Int]](List(1, 2, 3))
Only ClassTag
will lead the pattern matching to None
(which is the expected behavior), the first two commented lines will come up with Some
branch.
It seems that ClassTag
can reflect on object's type on runtime, while TypeTag
can't. But isn't TypeTag
a superset of ClassTag
? I would like to know the explanation as detailed as possible. Thank you.
A TypeTag is completely compiler-generated, that means that the compiler creates and fills in a TypeTag when one calls a method expecting such a TypeTag . There exist three different forms of tags: scala. reflect. ClassTag.
A ClassTag[T] stores the erased class of a given type T , accessible via the runtimeClass field. This is particularly useful for instantiating Array s whose element types are unknown at compile time.
A Manifest[T] is an opaque descriptor for type T. Its supported use is to give access to the erasure of the type as a Class instance, as is necessary for the creation of native Arrays if the class is not known at compile time.
Scala reflection enables a form of metaprogramming which makes it possible for programs to modify themselves at compile time. This compile-time reflection is realized in the form of macros, which provide the ability to execute methods that manipulate abstract syntax trees at compile-time.
this page will help you!
take a look :)
https://medium.com/@sinisalouc/overcoming-type-erasure-in-scala-8f2422070d20
add more detail, since only link answer is not appropriate...
ClassTag : runtime information about value, but not good with generic style
TypeTag : runtime information about type
e.g.
object Test extends App {
import scala.reflect.ClassTag
def func[T : ClassTag](o: Any): Unit = {
o match {
case x: T => println(x)
case _ => println(None)
}
}
func[List[String]](List(1, 2, 3)) // List(1, 2, 3), not None!!! with List[String] type parameter... ClassTag only recognize List scale, not List[T]
import scala.reflect.runtime.universe._
def func2[T](o: T)(implicit tag: TypeTag[T]): Unit = {
tag.tpe match {
case TypeRef(utype, usymbol, args) => println(args.toString)
case _ => println(None)
}
}
func2(List(1, 2, 3)) // List(Int)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With