本文介绍了为什么`.asInstanceOf` 有时会抛出,有时不会?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图回答这个问题,因为我以为我知道答案.事实证明,我知道的还不够多:/

I was trying to answer this question, as I thought I knew the answer.Turns out, I did not know quite enough :/

这是我做过的测试:

class Inst[T] {
  def is(x: Any) = scala.util.Try { as(x) }.isSuccess
  def as(x: Any): T = x.asInstanceOf[T]
}

scala> new Inst[String].is(3)
res17: Boolean = true

scala> new Inst[String].as(3)
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
 ... 33 elided

这里发生了什么?为什么只有第二次调用 as 抛出,而不是第一个?

What is going on here? Why does only the second call to as throw, but not the first one?

推荐答案

这是因为 class-cast-exception 仅在您对值执行某些操作时才会抛出,在转换后对其调用方法.例如,在 REPL 中,您将在第二种情况下调用 toString.注意:

This is because the class-cast-exception is only thrown when you do something with the value, call a method on it after the cast. In the REPL for example, you would have a toString call in the second case. Note:

new Inst[String].as(3); ()           // nothing happens
new Inst[String].as(3).toString; ()  // exception

这需要额外步骤的原因是 Inst[T] 是泛型的,类型参数 T 在运行时被删除;只有当调用站点(具有 T 类型的静态知识)尝试对结果调用方法时,才会发生实际的类型检查.

The reason why this takes the extra step is that Inst[T] is generic with type parameter T which is erased at runtime; only when the call-site (that has a static knowledge of type T) tries to call a method on the result, the actual type check occurs.

对于您的后续问题,toString 定义在任何对象上,并且由于 T 是通用的,因此您有一个装箱整数 (<: AnyRef) 和 toStringprintlnis 方法中成功.所以 Try 会失败的另一个例子是:

For your follow-up question, toString is defined on any object and since T is generic you have a boxed integer (<: AnyRef) and toString and println succeed within the is method. So another example where the Try would fail is this:

class Inst[T] {
  def foo(x: Any)(implicit ev: T <:< String) = scala.util.Try {
    ev(as(x)).reverse
  }.isSuccess
}

new Inst[String].foo(3)  // false!

这篇关于为什么`.asInstanceOf` 有时会抛出,有时不会?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 01:27