0

私が持っているとします:

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

注意。List の types パラメータを見つけることができるので、これは JVM タイプの消去による問題ではないようです。パラメータの型が java.lang.[numbers] である場合、scala コンパイラはこの型情報を破棄するようです。

アップデート:

次の実験により、このタイプの情報利用可能であると思われます。次のように定義するとします。

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

X.class は jar 経由でインポートされます。このケースが正しくコンパイルに失敗するためには、完全な型情報が X.class で利用可能でなければなりません。

更新 2:

Java シリアライゼーション ライブラリの scala 拡張機能を作成していると想像してください。以下を実装する必要があります。

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 を提供する必要があります (つまり、コンパイル時に)。

それで、解決策への 1 つのパス... いくつかの clz:Class[_] が与えられた場合、そのメソッドの戻り値の型の TypeToken を特定できますか? scala コンパイラがタイプの不一致エラーを正しく生成するには、この情報が .class ファイルに (どこかに) 含まれている必要があるため、明らかにこれが可能です (上記を参照)。

4

1 に答える 1

1

Java バイトコード レベルでIntは、 は別のもの (明らかにObject)として表現する必要がListあります。これが、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 への対応:Class[_]オブジェクトではなくミラーを取得するには、scala リフレクションを使用する必要があります。必要に応じて、クラス名を使用できます。

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)

本当にそのクラスしかないのなら、そのクラスだけをロードするクラスローダーを作成できますか? ただし、クラスや値さえも持たないユースケースは想像できません。

于 2015-01-07T08:39:17.660 に答える