Как сопоставить классы «логических» типов и «логических» типов? - PullRequest
4 голосов
/ 08 октября 2011

Рассмотрим следующий код:

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

Ответы [ 3 ]

3 голосов
/ 08 октября 2011

Когда отражение 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 решением.

2 голосов
/ 08 октября 2011

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

Во-первых, вместо 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
2 голосов
/ 08 октября 2011

На 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").

...