Scala:为什么 asInstanceOf 可以接受类型参数但 isInstanceOf 不能?
Scala: Why asInstanceOf can accept a type parameter but isInstanceOf can not?
这是 REPL (scala 2.11) 中的人为实验:
scala> class Foo[T] {
| def as(x: Any) = x.asInstanceOf[T]
| }
defined class Foo
scala> val foo = new Foo[String]
foo: Foo[String] = Foo@65ae6ba4
scala> val x: Any = 123
x: Any = 123
scala> foo.as(x) // expected
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
... 33 elided
scala> val y: Any = "abc"
y: Any = abc
scala> foo.as(y)
res1: String = abc
scala> class Bar[T] {
| def is(x: Any) = x.isInstanceOf[T]
| }
<console>:12: warning: abstract type T is unchecked since it is eliminated by erasure
def is(x: Any) = x.isInstanceOf[T]
^
defined class Bar
scala> val bar = new Bar[String]
foo: Foo[String] = Foo@1753acfe
scala> val x: Any = 123
x: Any = 123
scala> bar.is(x) // unexpected
res2: Boolean = true
scala> val y: Any = "abc"
y: Any = abc
scala> bar.is(y)
res3: Boolean = true
我知道由于类型擦除,类型参数非常有限,但仍然对 asInstanceOf 和 isInstanceOf 之间的不同行为感到困惑。
想知道是否有人对此有任何见解?谢谢!
嗯,你必须知道,类型参数在运行时是不可用的,它们携带的所有信息只能供编译器使用。现在,asInstanceOf
只是一个强制转换,编译器只需要它来强制执行类型兼容性,而在运行时它根本不做任何事情:引用就是引用,关于底层对象的类型.
isInstanceOf
另一方面是相反的:编译器对此一无所知,它只是一个函数调用。它在运行时执行以检查给定对象是否为预期类型。但是类型参数在运行时不可用,那么它怎么知道要检查哪种类型呢?因此,它需要一个真正的 Class
参数。
这是 REPL (scala 2.11) 中的人为实验:
scala> class Foo[T] {
| def as(x: Any) = x.asInstanceOf[T]
| }
defined class Foo
scala> val foo = new Foo[String]
foo: Foo[String] = Foo@65ae6ba4
scala> val x: Any = 123
x: Any = 123
scala> foo.as(x) // expected
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
... 33 elided
scala> val y: Any = "abc"
y: Any = abc
scala> foo.as(y)
res1: String = abc
scala> class Bar[T] {
| def is(x: Any) = x.isInstanceOf[T]
| }
<console>:12: warning: abstract type T is unchecked since it is eliminated by erasure
def is(x: Any) = x.isInstanceOf[T]
^
defined class Bar
scala> val bar = new Bar[String]
foo: Foo[String] = Foo@1753acfe
scala> val x: Any = 123
x: Any = 123
scala> bar.is(x) // unexpected
res2: Boolean = true
scala> val y: Any = "abc"
y: Any = abc
scala> bar.is(y)
res3: Boolean = true
我知道由于类型擦除,类型参数非常有限,但仍然对 asInstanceOf 和 isInstanceOf 之间的不同行为感到困惑。
想知道是否有人对此有任何见解?谢谢!
嗯,你必须知道,类型参数在运行时是不可用的,它们携带的所有信息只能供编译器使用。现在,asInstanceOf
只是一个强制转换,编译器只需要它来强制执行类型兼容性,而在运行时它根本不做任何事情:引用就是引用,关于底层对象的类型.
isInstanceOf
另一方面是相反的:编译器对此一无所知,它只是一个函数调用。它在运行时执行以检查给定对象是否为预期类型。但是类型参数在运行时不可用,那么它怎么知道要检查哪种类型呢?因此,它需要一个真正的 Class
参数。