我写了这段代码
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是不必要的,因为第一个对象本身就是类型转换。没有?
答案 0 :(得分:3)
您必须删除对recover
的通话。无论如何都不需要它,因为你在match
中处理错误案例,但它会弄乱代码的类型和正确性。
考虑类型:Try { /* ... */.asInstanceOf[BaseClass] }
类型为Try[BaseClass]
。
然后Try { /* ... */ } recover { case _ => Option.empty[(String, BaseClass)] }
是Try
和BaseClass
的常见超类型的Option[(String, BaseClass)]
,因此它是Try[AnyRef]
。
因此,在case Success(bc) =>
的匹配内,此bc
具有类型AnyRef
,并且在运行时,它可以是BaseClass
或None
的实例。如果来自Guice的原始抓取BaseClass
失败,则此bc
为None
,并且您获得ClassCastException
的附加isInstanceOf
。