2011-10-08 101 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