为了能够使用typeOf、classOf,需要先导入必需的库
import scala.reflect.runtime.universe._
1. 类型指的是type,类指的是class
2. 如果是类型,可用typeOf[A]获取类型信息
class A
typeOf[A]
3. 如果是类型,结合typeOf和<:<查看是否是子类型
class A
class B extends A
class C extends B
typeOf[B] <:< typeOf[A] // true, B是A的直接子类
typeOf[C] <:< typeOf[A] // true,C是A的间接子类
<:<一般会出现在隐式参数中,用于类型约束或定义联合类型
class A
class B extends A
class C extends B
val a = new A
val b = new B
val c = new C
def test[T](c: T)(implicit ev: T <:< A) = println("ok") // T是A的直接或间接子类,对应这里的B和C
test(a) // ok,传入对象的类是A
test(b) // ok,传入对象的类是A的直接子类
test(c) // ok,传入对象的类是A的间接子类
4. 如果是类,可用classOf[A]获取类的信息
class A
classOf[A] // 返回Class[A] = class A
5. 如果是对象,可以调用getClass获取类型信息
class A
val a = new A
a.getClass
注意:对象a中能够放入的数据类型必需是A的子类,满足里氏替换原则
6. 如果是对象,则一定具有相应的类型this.type,可以使用typeOf和<:<比较当前单例是否是某类型或其子类的投影
// 判断是否为对象A的类型
object A
val a = A.type
typeOf[a.type] <:< typeOf[A] // true
// 判断是否为类的投影
class A
class B extends A
val a = new B
typeOf[a.type] <:< typeOf[A] // true
typeOf[a.type] <:< typeOf[B] // true
7. 如果是object,不可用typeOf[A]和classOf[A]
object a
typeOf[a] // 报错
classOf[a] // 报错
8. 如果是嵌套类的内部类,getClass相同,classOf相同,但typeOf不同
class A{class B}
val a1 = new A
val a2 = new A
val b1 = new a1.B
val b2 = new a2.B
b1.getClass == b2.getClass // true,类型都是class A$B
classOf[a1.B] == classOf[a2.B] // true,类型都是class A$B
typeOf[a1.B] == typeOf[a2.B] // false,内部类型依赖外部实例,而外部实例不同,因此内部类型不同
9. 类型一致,则类一致,反之不然
classOf[List[Int]] == classOf[List[String]] // true
typeOf[List[Int]] == typeOf[List[String]] // false