scala中对泛型数组的支持,主要是利用隐式转换捕获泛型的类型,存储在manifest中
直接上代码
import scala.reflect.ClassTag class Rdd[T: ClassTag] { def mkArray[T:ClassTag](elems: T*): Array[T] = { // 获取T的实际类型 var clazz: ClassTag[T] = implicitly[ClassTag[T]] if (classOf[String] == clazz.runtimeClass) { print("RunTime Type T is java.lang.String") } if (classOf[Integer] == clazz.runtimeClass) { print("RunTime Type T is java.lang.Integer") } println(clazz) Array[T](elems: _*) } // 这个方法和上面那个方法实际上是一样的,而构建泛型数组是必须要这样一个显示的证明的,而对于普通的类泛型则不需要 // 但ClassTag也能捕获运行时泛型的实例 // def mkArray[T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T]) = { // var clazz: ClassTag[T] = implicitly[ClassTag[T]] //evidence // if (classOf[String] == clazz.runtimeClass) { // println("string") // } // print(evidence$1) // Array[T](elems: _*) // } def mkList[T](elems: T*) = { // var clazz: ClassTag[T] = implicitly[ClassTag[T]] //evidence // if (classOf[String] == clazz.runtimeClass) { // println("string") // } elems } def mkSet(elems: T*): Set[T] = { Set(elems: _*) } } object ClassTagApp extends App { private val stringRdd = new Rdd[String] private val stringArrz = stringRdd.mkArray("1", "2", "3") private val stringListz = stringRdd.mkList("1", "2", "3") private val stringSet = stringRdd.mkSet("1", "2", "3") private val intRdd = new Rdd[Int] private val intArrayz = intRdd.mkArray(1, 2, 3) private val intListz: Seq[Int] = intRdd.mkList(1, 2, 3) private val intSetz = intRdd.mkSet(1, 2, 3) }对于泛型数组而言,构建泛型数组一定需要Classtag
对于泛型而言,带上ClassTag也可以运行时捕捉一些运行信息,做一些额外的事
var clazz: ClassTag[T] = implicitly[ClassTag[T]] //evidence if (classOf[String] == clazz.runtimeClass) { println("string") }
这段代码就是捕捉隐式转换的证据(显示) evidence,
可以根据evidence 判断当前的泛型式什么类
最后写一个java与scala对classTag的应用
java
public static <T> T safe(T t,Class<T> clazz){ try { return Optional.ofNullable(t).orElse(clazz.newInstance() ); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }
scala
def safe[T](t:T)(implicit classTag: ClassTag[T]): T = { Optional.ofNullable(t).orElse(classTag.runtimeClass.newInstance().asInstanceOf[T]) }
String safe = Op.safe(null, ClassTag$.MODULE$.<String>apply(String.class));
var o=new Object o="" var str = Op.safe(o) println(str)
对于java 版要获取泛型的一个实例,必须传入class的实例,对于scala变成,implicit class由编译器添加,java 如果要用的话就得手动添加classTag了