美文网首页
scala 与 java泛型数组

scala 与 java泛型数组

作者: 编程易行 | 来源:发表于2017-04-16 22:31 被阅读383次

    java 泛型数组初始化

    public class GenericArray<T> {
    
        private T[] arr;
    
        public GenericArray(){
            arr = new T[10]; //编译错误
        }
    
    }
    

    使用这样的方式初始化java的数组会出错,因为java不支持泛型数组。按照我的理解,java 初始化数组时候,需要知道数组的确切类型,但是泛型是编译后擦除的。所以运行时,无法知道数组的确切类型。所以java不支持以 new T[] 方式初始化一个数组。

    如果想进行初始化,可以通过这样的方式

    T[] arr=(T[]) new Object[10];
    

    scala的泛型数组

    那么同样的场景,在scala中如何实现呢

    class ScalaGenericArray[T]{
      val arr: Array[T] = new Array[T](10)
    }
    
    object ScalaGenericArray{
      def main(args: Array[String]): Unit = {
        val arr = new ScalaGenericArray[String]
      }
    }
    

    看起来很自然,但是在运行时候会报错:

    Error:(9, 23) cannot find class tag for element type T
    val arr: Array[T] = new Array[T](10)

    原因和java的一样,虚拟机中,泛型相关的类型信息会被擦除,所以无法将T解释成实际类型String

    那么如何做呢,此处我们需要将类型的信息以一个参数的方式传进去

    class ScalaGenericArray[T](implicit classTag:ClassTag[T] ){ //让编译器帮我们传入类型信息
    
      val arr: Array[T] = new Array[T](10)
    
    }
    
    object ScalaGenericArray{
      def main(args: Array[String]): Unit = {
        val arr = new ScalaGenericArray[String]
      }
    }
    
    1. 感觉这种方式有点类似于java为了获取一个泛型的信息,将类以参数的形式传入函数参数中
    public <T> T test(Class<T> clazz) {
            System.out.println(clazz);
            //...
    }
    
    1. 当然此处的ClassTag也可以使用Manifest,但是在scala 2.10.0后就不推荐使用了

    2. 这样写比较复杂,scala也提供另一种简单的方式,上下文界定

    class ScalaGenericArray[T: ClassTag] {//此处不再需要提供参数
      val arr: Array[T] = new Array[T](10)
    }
    
    object ScalaGenericArray {
      def main(args: Array[String]): Unit = {
        val arr = new ScalaGenericArray[String]
      }
    }
    

    这是scala的语法糖,T:ClassTag 告诉scala存在一个类型为ClassTag[T] 的隐式参数

    相关文章

      网友评论

          本文标题:scala 与 java泛型数组

          本文链接:https://www.haomeiwen.com/subject/jlqzattx.html