简体   繁体   English

Scala:为什么asInstanceOf可以接受类型参数但isInstanceOf不能接受?

[英]Scala: Why asInstanceOf can accept a type parameter but isInstanceOf can not?

Here's the contrived experiments in REPL (scala 2.11): 这是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

I know type parameter is quite limited due to type erasion, but still confused by the different behaviours between asInstanceOf and isInstanceOf here. 我知道类型参数由于类型擦除而非常有限,但仍然被asInstanceOf和isInstanceOf之间的不同行为所困惑。

Wonder if someone has any insight about that? 想知道是否有人对此有任何见解? Thanks! 谢谢!

Well, you must know, that type parameters are not available at runtime, all information they carry can only be used by the compiler. 嗯,您必须知道,类型参数在运行时不可用,它们携带的所有信息只能由编译器使用。 Now, asInstanceOf is just a cast, it is only needed to the compiler to enforce the type compatibility, and at runtime it doesn't do anything at all: a reference is a reference, regarding of the type of underlying object. 现在, asInstanceOf只是一个强制转换,只需要编译器强制执行类型兼容性,并且在运行时它根本不做任何事情:引用是关于底层对象类型的引用。

isInstanceOf on the other hand is the opposite: compiler does not know anything about it, it's just a function call. 另一方面, isInstanceOf则相反:编译器对它一无所知,它只是一个函数调用。 It is executed at runtime to check whether the given object is of the expected type. 它在运行时执行以检查给定对象是否是预期类型。 But the type parameter is not available at runtime, so how would it know which type to check against? 但是类型参数在运行时不可用,那么它如何知道要检查哪种类型? For this reason, it needs a real Class argument. 因此,它需要一个真正的Class参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM