scala manifest和classmanifest的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala manifest和classmanifest的区别相关的知识,希望对你有一定的参考价值。

Manifest是scala2.8引入的一个特质,用于编译器在运行时也能获取泛型类型的信息。在JVM上,泛型参数类型T在运行时是被“擦拭”掉的,编译器把T当作Object来对待,所以T的具体信息是无法得到的;为了使得在运行时得到T的信息,scala需要额外通过Manifest来存储T的信息,并作为参数用在方法的运行时上下文。
def test[T] (x:T, m:Manifest[T]) ...

有了Manifest[T]这个记录T类型信息的参数m,在运行时就可以根据m来更准确的判断T了。但如果每个方法都这么写,让方法的调用者要额外传入m参数,非常不友好,且对方法的设计是一道伤疤。好在scala中有隐式转换、隐式参数的功能,在这个地方可以用隐式参数来减轻调用者的麻烦。

获取class manifests的两种基本方式:
1 def classOf[T <: Any](implicit m: scala.reflect.Manifest[T]): Class[T] = m.erasure.asInstanceOf[Class[T]
通过implicit m: scala.reflect.Manifest[T]声明一个隐式参数,这样scala编译器能在编译时提供T的类型信息了

2 def classOf[T <: Any : Manifest] : Class[T] = manifest[T].erasure.asInstanceOf[Class[T]

其中 T <: Any : Manifest,拆分成两部分来看
T <: Any
T 是Any的子类型(即可以是任意基本类型scala.AnyVal 和引用类型 scala.AnyRef)

T : Manifest 相当于对classOf 方法currying
隐式增加参数列表如下:(implicit evidence$1: Manifest[T]),
通过manifest[T] 方法即可获取Manifest实例

可见形式1 和形式2实质是一样的。

应用:
1最常见的是获取类型参数的Class,形如someMethod[Type]
如akka中源码: def actorOf[T <: Actor : Manifest]: ActorRef = actorOf(manifest[T].erasure.asInstanceOf[Class[_ <: Actor])

class Worker extends Actor
def receive =
case Work(start, nrOfElements) =>
self reply Result(calculatePiFor(start, nrOfElements)) // perform the work



就可以如此使用了: val workerActorRef = actorOf[Worker]

2 编程方式创建范型数组
def evenElems[T: ClassManifest](xs: Vector[T]): Array[T] =
val arr = new Array[T]((xs.length + 1) / 2)
for (i <- 0 until xs.length by 2)
arr(i / 2) = xs(i)
arr


scala> evenElems(Vector("a","b","c"))
res: Array[java.lang.String] = Array(a, c)
参考技术A 这样啊 那你把a.jar 解压出来 变成CLASS 放到项目中。 然后打包就可以了 另一外办法 新建一文件夹A 在里面建一个lib文 件夹 然后把打包的b.jar放到A 文件夹下 在b.jar里面得有 META-INF文件夹下 MANIFEST.MF配置文件 Manifest-Version

以上是关于scala manifest和classmanifest的区别的主要内容,如果未能解决你的问题,请参考以下文章

scala-创建泛型数组(T: Manifest)

Scala类参数化中附加冒号的含义

从Scala文件创建jar文件

scala 上下文绑定ClassTagTypeTagClassManifestManifest

什么是 TypeTag 以及如何使用它?

001_manifest.json手册