zl程序教程

您现在的位置是:首页 >  后端

当前栏目

scala的类与类型

scala 类型
2023-09-14 08:58:00 时间
h2 > 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)

Reference http://hongjiang.info/scala-type-system-classof-and-getclass/
http://hongjiang.info/scala-type-and-class/
http://www.scala-lang.org/files/archive/nightly/docs/library/index.html#scala.reflect.ClassTag
http://blog.csdn.net/lonelyroamer/article/details/7868820


大数据Scala系列之类 大数据Scala系列之类 Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。 如果没有指定访问修饰符符,默认情况下,Scala 对象的访问级别都是 public。