首页 > 解决方案 > 为什么我需要一个额外的 asInstanceOf

问题描述

我写了这段代码

listOfClassNames.map{ className => 
  Try {
    GuiceInjector.getInstance(Class.forName(className)).asInstanceOf[BaseClass]
  } recover {
    case _ => Option.empty[(String, BaseClass)]
  } match {
    case Success(bc) => Some((className, bc))
    case _ => Option.empty[(String, BaseClass)]
  }
}

上面的代码抛出错误

type mismatch;
[error]  found   : List[Option[(String, Object)]]
[error]  required: List[Option[(String, BaseClass)]]

现在,如果我将代码更改为

listOfClassNames.map{ className => 
  Try {
    GuiceInjector.getInstance(Class.forName(className)).asInstanceOf[BaseClass]
  } recover {
    case _ => Option.empty[(String, BaseClass)]
  } match {
    case Success(bc) => Some((className, bc.asInstanceOf[BaseClass]))
    case _ => Option.empty[(String, BaseClass)]
  }
}

现在它起作用了。但根据我的说法,第二个 asInstanceOf 是不必要的,因为第一个对象本身是类型转换的。不?

标签: scala

解决方案


您必须删除对 的调用recover。无论如何都不需要它,因为您在内部处理错误案例match,但它会弄乱代码的类型和正确性。

考虑类型:Try { /* ... */.asInstanceOf[BaseClass] } 有类型Try[BaseClass]

然后Try { /* ... */ } recover { case _ => Option.empty[(String, BaseClass)] }是andTry的常见超类型,所以它是。BaseClassOption[(String, BaseClass)]Try[AnyRef]

因此,在case Success(bc) =>this中的 match 内部bc有 type AnyRef,并且在运行时它可以是BaseClassor的一个实例NoneBaseClass如果从 Guice的原始获取失败,这bcNone,你会得到一个ClassCastException带有附加的isInstanceOf.


推荐阅读