1. ホーム
  2. java

[解決済み] Java java.lang.Class<T> Object の Scala 版。

2022-04-16 11:07:05

質問

質問は例によって説明するのが一番です。

JavaでJPA EntityManagerを使用する場合、次のようになります(Accountは私のEntityクラスです)。

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

Scalaで、私の素朴な試みは。

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

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

どのように解決するのですか?

によると、" Scalaの型システム "です。

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 .

( ジェームス・ムーア によると、このチケットは2011年11月、つまり2年後に修正されているとのことです。

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