Java java.lang.Class <T>オブジェクトに相当するScala


183

質問は例で最もよく説明されます:

JPA EntityManagerのJavaでは、次のことができます(アカウントは私のEntityクラスです)。

Account result = manager.find(Account.class, primaryKey);

Scalaでは、私の素朴な試みは次のとおりです。

val result = manager.find(Account.class, primaryKey)

しかしAccount.class、Scalaで使用しようとすると、このようにはならないようです。ScalaでAccountクラスのjava.lang.Classオブジェクトを指定するにはどうすればよいですか?


VonCはすでに回答を提供していますが、ScalaとErasureに関する自分の質問/回答を見てください。あなたがやろうとしていることとは異なる方法で物事を行うためのアイデアを提供してくれると思います。
ダニエルC.ソブラル

回答:


264

The Scala Type System」によると、

val c = new C
val clazz = c.getClass              // method from java.lang.Object
val clazz2 = classOf[C]             // Scala method: classOf[C] ~ C.class
val methods = clazz.getMethods      // method from java.lang.Class<T>

このclassOf[T]メソッドは、Scala型のランタイム表現を返します。これはJava式に似ていますT.class
を使用するclassOf[T]と、情報が必要なタイプがある場合に便利ですが、タイプgetClassのインスタンスから同じ情報を取得する場合にも便利です。

しかし、classOf[T]getClassのgetClassの場合には、JVM上のタイプ消去の効果を反映して、わずかに異なる値を返します。

scala> classOf[C]
res0: java.lang.Class[C] = class C

scala> c.getClass
res1: java.lang.Class[_] = class C

そのため、以下は機能しません

val xClass: Class[X] = new X().getClass //it returns Class[_], nor Class[X]

val integerClass: Class[Integer] = new Integer(5).getClass //similar error

の返品タイプに関するチケットgetClassがあります。

James Mooreは、チケットは「今」、つまり2年後の2011年11月に修正されたと報告しています
。2.9.1では、次のgetClassようになります。

scala> "foo".getClass 
       res0: java.lang.Class[_ <: java.lang.String] = class java.lang.String

2009年に戻る:

ScalaがgetClass()からの戻りをjava.lang.Class [T] forSome {val T:C}として扱う場合に役立ちます。Cは、getClassが存在する式の静的型の消去のようなものです呼ばれる

それは私がクラスを内省したいがクラスインスタンスを必要としないはずである場合に次のようなことをさせるでしょう。
また、イントロスペクトするクラスのタイプを制限したいので、Class [_ <:Foo]を使用します。しかし、これにより、キャストなしでFoo.getClass()を使用してFooクラスを渡すことができなくなります。

注:に関してgetClass、考えられる回避策は次のとおりです。

class NiceObject[T <: AnyRef](x : T) {
  def niceClass : Class[_ <: T] = x.getClass.asInstanceOf[Class[T]]
}

implicit def toNiceObject[T <: AnyRef](x : T) = new NiceObject(x)

scala> "Hello world".niceClass                                       
res11: java.lang.Class[_ <: java.lang.String] = class java.lang.String

4
参考までに、言及されたチケット@VonCは、2011年6月22日に修正済みとマークされました。2.9.1では、getClassは次のことを行います:scala> "foo" .getClass res0:java.lang.Class [_ <:java.lang.String] = class java.lang.String
James Moore

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.