考虑以下代码:
object U { def foo(s:String) = true }
val boolType = Class.forName("java.lang.Boolean")
val retType = U.getClass.getMethods.find(_.getName == "foo").get.getReturnType
boolType == retType // evaluates to false (*)
println (boolType) // prints "class java.lang.Boolean"
println (retType) // prints "boolean"
我希望retType
与boolType
在标记为(*)
的行中匹配。如何自动地将盒装类型和未盒装类型的类等同起来?
retType.getCanonicalName == "boolean"
[Edit2:]上下文:我正在编写一些代码来自动调用基于表单名称的方法。代码应该从方法中提取返回类型等,并返回适当的答案。例如,使用以下代码片段:
object someObject {}
val validTypes:Array[Class[_]] = Array(Class.forName("java.lang.String"),
someObject.getClass,
Class.forName("java.lang.Boolean"))
object U { def foo(s:String) = true } // can contain more methods
def getRetType(name:String) =
U.getClass.getMethods.find(_.getName == name).get.getReturnType
println ("Type is "+(if (validTypes.contains(getRetType("foo"))) "valid" else "invalid"))
当Java反射想要表示基本返回类型时,它使用与包装器类不同的Class
实例。因此,在Java中,boolean
返回类型由java.lang.Boolean.TYPE
表示(在Java中也可以作为boolean.class
访问,在Scala中可以作为classOf[Boolean]
访问)。
所以你想要
scala> U.getClass.getMethods.find(_.getName == "foo").get.getReturnType ==
java.lang.Boolean.TYPE
res7: Boolean = true
编辑:我猜与classOf[Boolean]
比较将是一个不太特定于JVM的解决方案。
在JVM上,java.lang.Boolean
是引用类型。例程返回一个scala Boolean
,它是java原语boolean
。它不是JVM中的类。它的类型是java.lang.Boolean.TYPE
,而不是classOf[Boolean]
(java中的java.lang.Boolean.class
),这是Class.forName("java.lang.Boolean")
的类型。
我认为你唯一的解决方案是有一个显式映射。既然您问如何"(自动地)使已装箱类型和未装箱类型的类相等",我将展示一种定义比较函数的优雅方法。
首先,当类型在编译时已知时,可以使用classOf[Type]
代替Class.forName
。使用它,您可以定义非盒装类型到盒装类型的规范化映射:
import java.{lang => jl}
val map = Map[Class[_], Class[_]](classOf[Boolean] -> classOf[jl.Boolean],
classOf[Int] -> classOf[jl.Integer]) //XXX add other entries
然后你可以定义一个比较函数:
def cmp(lhs: Class[_], rhs: Class[_]) =
//Canonicalize before comparing
map.getOrElse(lhs, lhs) == map.getOrElse(rhs, rhs)
并测试它:
scala> cmp(classOf[Boolean], classOf[jl.Boolean])
cmp(classOf[Boolean], classOf[jl.Boolean])
res13: Boolean = true
scala> cmp(classOf[Boolean], classOf[jl.Integer])
cmp(classOf[Boolean], classOf[jl.Integer])
res16: Boolean = false
为了澄清classOf
和Boolean.TYPE
之间的关系,这里有几个REPL交互:
scala> classOf[java.lang.Boolean] == java.lang.Boolean.TYPE
res7: Boolean = false
scala> classOf[Boolean] == java.lang.Boolean.TYPE
res8: Boolean = true