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

3 回答 3

3

当 Java 反射想要表示原始返回类型时,它使用Class与包装类不同的实例。因此,在 Java 中,boolean返回类型由 a 表示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进行比较将是一个不太具体的解决方案。

于 2011-10-08T13:51:18.603 回答
2

在JVM上,java.lang.Boolean是引用类型。您的例程返回一个 scala Boolean,它是 java 原语boolean。那不是JVM中的一个类。它的类型是java.lang.Boolean.TYPE,而不是classOf[Boolean]java.lang.Boolean.class在 java 中),这是你得到的Class.forName("java.lang.Boolean")

于 2011-10-08T13:33:21.927 回答
2

I think your only solution is to have an explicit mapping. Since you ask how to "(automatically) equate classes of boxed and unboxed types", I show an elegant way to define a comparison function.

First, instead of Class.forName you can use classOf[Type], when the type is known at compile-time. Using this, you can define a canonicalizing mapping of unboxed to boxed types:

import java.{lang => jl}
val map = Map[Class[_], Class[_]](classOf[Boolean] -> classOf[jl.Boolean],
  classOf[Int] -> classOf[jl.Integer]) //XXX add other entries

Then you can define a comparison function:

def cmp(lhs: Class[_], rhs: Class[_]) =
  //Canonicalize before comparing
  map.getOrElse(lhs, lhs) == map.getOrElse(rhs, rhs)

And test it:

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

To clarify the relation between classOf and Boolean.TYPE, here's a couple REPL interactions:

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

scala> classOf[Boolean] == java.lang.Boolean.TYPE
res8: Boolean = true
于 2011-10-08T15:11:25.990 回答