如何匹配“布尔”类型和“布尔”类型的类?

时间:2011-10-08 12:52:34

标签: scala reflection autoboxing

请考虑以下代码:

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"))

3 个答案:

答案 0 :(得分:3)

当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特定解决方案。

答案 1 :(得分:2)

在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")的结果。

答案 2 :(得分:2)

我认为您唯一的解决方案是拥有明确的映射。 既然你问如何“(自动)等同于盒装类型和非盒装类型”,我就会展示一种优雅的方式来定义比较函数。

首先,在编译时知道类型时,可以使用Class.forName而不是classOf[Type]。使用此方法,您可以定义unboxed到boxed类型的规范化映射:

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

为了澄清classOfBoolean.TYPE之间的关系,这里有几个REPL互动:

scala> classOf[java.lang.Boolean] == java.lang.Boolean.TYPE
res7: Boolean = false

scala> classOf[Boolean] == java.lang.Boolean.TYPE
res8: Boolean = true
相关问题