zoukankan      html  css  js  c++  java
  • Scala的类与类型

    类和类型

    List<String>和List<Int>类型是不一样的,但是jvm运行时会采用泛型擦除。导致List<String>和List<Int>都是Class<List>.为了得到正确的类型,需要通过反射。

    泛型擦除

    Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。泛型擦除是为了兼容jdk1.5之前的jvm,在这之前是不支持泛型的。

    classOf与getClass方法的差异

    scala> class  A
    scala> val a = new A
    
    scala> a.getClass
    res2: Class[_ <: A] = class A
    
    scala> classOf[A]
    res3: Class[A] = class A

    上面显示了两者的不同,getClass 方法得到的是 Class[A]的某个子类,而 classOf[A] 得到是正确的 Class[A],但是去比较的话,这两个类型是equals为true的

    classOf和getClass

    classOf获取运行时的类型。classOf[T] 相当于 java中的T.class

      val listClass = classOf[List[_]]
       * // listClass is java.lang.Class[List[_]] = class scala.collection.immutable.List
       val mapIntString = classOf[Map[Int,String]]
       * // mapIntString is java.lang.Class[Map[Int,String]] = interface scala.collection.immutable.Map
       * }}}

    而getClass:

    scala> class  A
    scala> val a = new A
    
    scala> a.getClass
    res2: Class[_ <: A] = class A
    
    scala> classOf[A]
    res3: Class[A] = class A

    上面显示了两者的不同,getClass 方法得到的是 Class[A]的某个子类,而 classOf[A] 得到是正确的 Class[A],但是去比较的话,这两个类型是equals为true的

    scala> a.getClass  == classOf[A]
    res13: Boolean = true

    这种细微的差别,体现在类型赋值时,因为java里的 Class[T]是不支持协变的,所以无法把一个 Class[_ < : A] 赋值给一个 Class[A]

    scala> val c:Class[A] = a.getClass
    <console>:9: error: type mismatch;

    类(class)与类型(type)是两个不一样的概念
    (在java里因为早期一直使用class表达type,并且现在也延续这样的习惯);类型(type)比类(class)更”具体”,任何数据都有类型。类是面向对象系统里对同一类数据的抽象,在没有泛型之前,类型系统不存在高阶概念,直接与类一一映射,而泛型出现之后,就不在一一映射了。比如定义class List[T] {}, 可以有List[Int] 和 List[String]等具体类型,它们的类是同一个List,但类型则根据不同的构造参数类型而不同。

    类型一致的对象它们的类也是一致的,反过来,类一致的,其类型不一定一致。

    scala> classOf[List[Int]] == classOf[List[String]]
    res16: Boolean = true
    
    scala> typeOf[List[Int]] == typeOf[List[String]]
    res17: Boolean = false

    ClassTag

    ClassTag[T]保存了被泛型擦除后的原始类型T,提供给运行时的。

    scala> def mkArray[T : ClassTag](elems: T*) = Array[T](elems: _*)
    mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]

    TypeTag

    TypeTag则保存所有具体的类型

    import scala.reflect.runtime.universe._
    def paramInfo[T](x: T)(implicit tag: TypeTag[T]): Unit = {
      val targs = tag.tpe match { case TypeRef(_, _, args) => args }
      println(s"type of $x has type arguments $targs")
    }
    scala> paramInfo(42)
    type of 42 has type arguments List()
    scala> paramInfo(List(1, 2))
    type of List(1, 2) has type arguments List(Int)

    可以看到,获取到的类型是具体的类型,而不是被擦除后的类型List(Any)

  • 相关阅读:
    20145223《Java程序程序设计》课程总结
    20145223《Java程序程序设计》第10周学习总结
    20145223《Java程序程序设计》实验报告5
    20145223《Java程序程序设计》第9周学习总结
    20145223 《Java程序程序设计》实验报告4
    20145223《Java程序程序设计》第8周学习总结
    20145223《Java程序设计》实验报告3
    20145223《Java程序程序设计》第7周学习总结
    20145223《Java程序程序设计》实验报告二
    node_promise
  • 原文地址:https://www.cnblogs.com/itboys/p/9208840.html
Copyright © 2011-2022 走看看