2015-01-07 115 views
0

假設我有:可能找到參數類型方法在Scala中的返回類型,其中參數是基本類型?

class X 
{ 
    val listPrimitive: List[Int] = null 
    val listX: List[X] = null 
} 

,我打印出來的返回類型Scala中的每個方法如下:

classOf[ComplexType].getMethods().foreach { m => println(s"${m.getName}: ${m.getGenericReturnType()}") } 

listPrimitive: scala.collection.immutable.List<Object> 
listX: scala.collection.immutable.List<X> 

所以......我能確定的是,LISTX的元素類型爲X,但有沒有什麼辦法通過反射來確定listPrimitive的元素類型實際上是java.lang.Integer? ...

val list:List[Int] = List[Int](123); 
val listErased:List[_] = list; 
println(s"${listErased(0).getClass()}") // java.lang.Integer 

NB。這似乎不是一個問題,由於JVM類型擦除,因爲我可以找到列表的類型參數。它看起來像scala編譯器拋出此類型信息IFF的參數類型是java.lang。[數字]。

UPDATE:

我懷疑這種類型的信息可用,由於下面的實驗。假設我定義了:

class TestX{ 
    def f(x:X):Unit = { 
    val floats:List[Float] = x.listPrimitive() // type mismatch error 
    } 
} 

和X.class通過jar導入。完整的類型信息必須在X.class中可用,以便這種情況正確無法編譯。

UPDATE2:

想象一下你正在寫一階擴展Java序列化庫。您需要實現:

def getSerializer(clz:Class[_]):Serializer 

功能需要做取決於是否不同的事情:我的問題

clz==List[Int] (or equivalently: List[java.lang.Integer]) 
clz==List[Float] (or equivalently: List[java.lang.Float]) 
clz==List[MyClass] 

的是,我將永遠只能看到:

clz==List[Object] 
clz==List[Object] 
clz==List[MyClass] 

因爲CLZ作爲clz.getMethods()(i).getGenericReturnType()提供給此函數。

從clz開始:Class [_]如何恢復丟失的元素類型信息?

它不清楚,我認爲TypeToken會幫助我,因爲它的用途:

typeTag[T] 

要求我提供T(即在編譯時)。

所以,一個解決方案的路徑...給定一些clz:Class [_],我可以確定它的方法的返回類型的TypeTokens?顯然,這是可能的,因爲這些信息必須包含在.class文件中,以便scala編譯器正確生成類型不匹配錯誤(參見上文)。

回答

1

由於List只能包含對象而不是基元,所以在java字節碼級別Int必須表示爲別的東西(顯然是Object)。所以這就是Java級別的反射可以告訴你的。但Scala的類型信息,爲你推斷,目前(在字節碼級它在一個註解,IIRC),所以你應該能夠使用Scala反射來檢查它:

import scala.reflect.runtime.universe._ 

val list:List[Int] = List[Int](123) 

def printTypeOf[A: TypeTag](a: A) = println(typeOf[A]) 

printTypeOf(list) 

響應UPDATE2:你應該使用scala反射來獲取鏡像,而不是Class[_]對象。您可以通過類名去,如果需要的話:

import scala.reflect.runtime.universe._ 

val rm = runtimeMirror(getClass.getClassLoader) 

val someClass: Class[_] = ... 

val scalaMirrorOfClass = rm.staticClass(someClass.getName) 
// or possibly rm.reflectClass(someClass) ? 

val someObject: Any = ... 

val scalaMirrorOfObject = rm.reflectClass(someObject) 

我想如果你真的有類,你可以創建一個只加載該類一個類加載器?儘管如此,我無法想象一個用例,即你不會擁有這個類,或者甚至是一個值。

+0

對象表示爲java.lang.Integer,當然。 但TypeTag不適用於對象和類型。我正在尋找一個方法的返回類型(這在編譯器中是清楚的,並且可以在類文件中找到)。 – user48956

+0

發現元素類型是Int(而不是java.lang.Integer)也解決了我的問題。但是,這些信息也丟失了。 – user48956

+0

我不明白。 'TypeTag'只是獲取類型的幫手;如果您正在使用scala反射檢查方法返回類型,則可以獲得您從'typeOf'獲得的相同類型表示。 – lmm

相關問題