给定的Java方法返回给定字符串的java.lang.Object
s。我想将此方法包装在Scala方法中,该方法将返回的实例转换为某种类型T
。如果转换失败,则该方法应返回None
。我正在寻找类似的东西:
def convert[T](key: String): Option[T] = {
val obj = someJavaMethod(key)
// return Some(obj) if obj is of type T, otherwise None
}
convert[Int]("keyToSomeInt") // yields Some(1)
convert[String]("keyToSomeInt") // yields None
(如何)使用Scala的反射API可以实现这一目标吗?我很清楚convert
的签名可能需要改变。
答案 0 :(得分:15)
您可以尝试shapeless的Typeable
,
scala> import shapeless._ ; import syntax.typeable._
import shapeless._
import syntax.typeable._
scala> def someJavaMethod(key: String): AnyRef =
| key match {
| case "keyToSomeInt" => 23.asInstanceOf[AnyRef]
| case "keyToSomeString" => "foo"
| }
someJavaMethod: (key: String)AnyRef
scala> def convert[T: Typeable](key: String): Option[T] =
| someJavaMethod(key).cast[T]
convert: [T](key: String)(implicit evidence$1: shapeless.Typeable[T])Option[T]
scala> convert[Int]("keyToSomeInt")
res0: Option[Int] = Some(23)
scala> convert[String]("keyToSomeString")
res1: Option[String] = Some(foo)
scala> convert[String]("keyToSomeInt")
res2: Option[String] = None
scala> convert[Int]("keyToSomeString")
res3: Option[Int] = None
答案 1 :(得分:13)
这就是ClassTag
if for:
import reflect.ClassTag
def convert[T : ClassTag](key: String): Option[T] = {
val ct = implicitly[ClassTag[T]]
someJavaMethod(key) match {
case ct(x) => Some(x)
case _ => None
}
}
它可以用作提取器来同时测试和转换为正确的类型。
示例:
scala> def someJavaMethod(s: String): AnyRef = "e"
someJavaMethod: (s: String)AnyRef
[...]
scala> convert[Int]("key")
res4: Option[Int] = None
scala> convert[String]("key")
res5: Option[String] = Some(e)
修改:请注意ClassTag
不自动取消装箱框原语。因此,例如,convert[Int]("a")
永远不会起作用,因为java方法返回AnyRef
,它必须是convert[java.lang.Integer]("a")
,依此类推其他原始类型。
Miles对Typeable
的回答似乎会自动处理这些边缘情况。