第46讲:ClassTag 、Manifest、ClassManifest、TypeTag代码实战及其在Spark中的应用源码解析学习笔记
应用最多的是classTag,其次是TypeTag.
实例代码:
创建数组,理论上讲创建泛型数组是不可以的,因为没有指定具体类型。
scala中运行时数组必须有具体类型。
引入manifest后就可以创建泛型数组
例1
def arrayMake[T: Manifest](first : T, second : T) = {
val r = new Array[T](2);r(0) = first; r(1) = second; r
/*T: Manifest叫T的上下文界定。有一个Manifest的T类型的隐式值,这个过程是隐式转换的过程。
*有这样的隐式值辅助我们构建Array[T],从而确定T的类型。
*编写代码及编译时并不知道T的具体类型。
*manifast是上下文界定,其实是假设T是整数,Array[T]就是Array[Int] */
}
arrayMake(1,2).foreach(println)
//要构建泛型对象,需要manifest来存储T的实际类型,
//在实际运行时,是作为参数用地方法运行的上下文中。
//是个隐式的过程,manifest可以记录T的具体类型,所以就可以获取它的类型。
例2
def manif[T](x: List[T])(implicit m : Manifest[T]) = {
//implicit m : Manifest[T]是个隐式参数,是虚拟机运行时传入的。
if (m <:< manifest[String])
//<:<下节再讲,m是manifest[String]类型的。
println("List string")
else
println("Some other type")
}
manif(List("Spark","Hadoop"))
manif(List(1,2))
manif(List("Scala",3))
例2的写法有点繁琐,所以推荐例1的写法,例1是简化写法,内部自动构建隐式参数。
例3:
val m = manifest[A[String]]
println(m)
val cm = classManifest[A[String]]
println(cm)
classManifest,Manifest信息获取方面弱。
manifest本身是有问题的。
依赖路径与实际类型判断有误。
所以又推出typeTag和classTag取代manifest和classManifest。
在spark源码中大部分都是lassTag和typeTag。
例4:
import scala.reflect.ClassTag
def mkArray[T: ClassTag](elems: T*) = Array[T](elems: _*)
mkArray(42,13).foreach(println)
mkArray("Japan",Brazil","Germany").foreach(println)
编写编译时不需要具体类型,运行时必须要有具体类型。
原因:scala运行在jvm虚拟机上,虚拟机运行任何对象时对象是泛型时是把泛型擦除掉的。
以上内容是从王家林老师DT大数据课程第46讲的学习笔记。
DT大数据微信公众账号:DT_Spark
王家林老师QQ:1740415547
王家林老师微信号:18610086859
我的百度网盘共享的DT大数据梦工厂王家林老师第1-90讲的视频内容:http://pan.baidu.com/s/1qWK9CMo