2011-10-08 103 views
4

考虑下面的代码:如何匹配“布尔”类型和“布尔”类型的类?

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

有趣的问题,但在什么情况下你需要它?你想在编译时或运行时检查它吗? – paradigmatic

+0

@paradigmatic我认为检查将在运行时完成。 – Jus12

回答

3

当Java反射希望代表原始返回类型,它使用Class情况是不一样的包装类。因此,在Java中,boolean返回类型由java.lang.Boolean.TYPE代表(这在Java中也为boolean.class访问,并在斯卡拉为classOf[Boolean])。

所以,你要

scala> U.getClass.getMethods.find(_.getName == "foo").get.getReturnType == 
    java.lang.Boolean.TYPE 
res7: Boolean = true 

编辑:我想这与classOf[Boolean]比较可能是一个相对JVM具体的解决方案。

+0

谢谢!使用'java.lang.Boolean.TYPE'工程! – Jus12

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")得到。

+0

Java原始布尔类的类是boolean.class,它确实存在于JVM中。 – EJP

+0

我不认为这说明它不存在 - 它说原始不是一个阶级。 –

2

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

首先,在编译时知道类型时,可以使用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 

澄清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 
+0

太好了。 – Jus12