2011-10-08 6 views
4

Рассмотрим следующий код:Как совместить классы типа «boolean» и «Boolean»?

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 в строке, помеченной (*). Как автоматически приравнивать классы классов в коробке и распакованных?

[Edit:] Я не думаю, что это лучшее решение, но один из способов является сделать сравнение 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, а в Scala - classOf[Boolean]).

Так что вы хотите

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

Edit: Я думаю, что сравнение с 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.lang.Boolean.class в java), это то, что вы получаете с Class.forName("java.lang.Boolean").

+0

Класс примитива boolean Java - это boolean.class, и он действительно существует в JVM. – EJP

+0

Я не думаю, что это говорит, что этого не существует - он говорит, что примитив не является классом. –

2

Я думаю, что ваше единственное решение - иметь явное сопоставление. Поскольку вы спрашиваете, как «(автоматически) приравнивать классы классов в коробке и распакованных», я показываю элегантный способ определения функции сравнения.

Во-первых, вместо Class.forName вы можете использовать classOf[Type], когда тип известен во время компиляции. Используя это, вы можете определить канонизации отображение распакованный в штучной упаковке типов:

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

Хороший ответ тоже. – Jus12

Смежные вопросы