Why does 1.asInstanceOf[T] not throw ClassCastExce

2019-08-22 14:50发布

问题:

scala> def g[T] = 1.asInstanceOf[T]
g: [T]=> T

scala> g[String]
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
  ... 32 elided

scala> { g[String]; 1 }
res0: Int = 1

But:

scala> def f = 1.asInstanceOf[String]
f: String

scala> { f; 1 }
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
  at .f(<console>:7)
  ... 32 elided

What is the logic here? How do I trigger ClassCastException in a type parametric function?

回答1:

This warning answers my question:

scala> def g[T] = 1.isInstanceOf[T]
<console>:7: warning: abstract type T is unchecked since it is eliminated by erasure
       def g[T] = 1.isInstanceOf[T]
                                ^

So asInstanceOf[T] is a compile-time cast. It has no effect at run-time. In the case where I got the ClassCastException it was raised not by asInstanceOf[T] but by the actual conversion that happened outside of the function.

The solution is to take a ClassTag and use classTag[T].runtimeClass.cast. This behaves slightly differently though: you can use asInstanceOf[Double] on an Int, but cast will fail with a ClassCastException. The solution to this problem then is to use Apache commons-lang's ClassUtils.isAssignable.



标签: scala