Setara scala dari Java java.lang.Class Obyek <T>

183

Pertanyaannya paling baik dijelaskan dengan sebuah contoh:

Di Java untuk JPA EntityManager, saya bisa melakukan hal berikut (Akun adalah kelas Entitas saya):

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

Di Scala, upaya naif saya adalah:

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

Tetapi ketika saya mencoba menggunakannya Account.classdi Scala, sepertinya tidak seperti ini. Bagaimana saya bisa menentukan objek java.lang.Class untuk kelas Akun di Scala?

Kekoa
sumber
VonC sudah memberikan jawabannya, tetapi lihatlah pertanyaan / jawaban saya sendiri di Scala & Erasure. Saya pikir itu mungkin memberi Anda ide untuk melakukan sesuatu dengan cara yang berbeda dari apa yang Anda coba.
Daniel C. Sobral

Jawaban:

264

Menurut " 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>

The classOf[T]Metode mengembalikan runtime representasi untuk jenis Scala. Ini analog dengan ekspresi Java T.class.
Penggunaan classOf[T]nyaman ketika Anda memiliki jenis yang Anda inginkan informasi, sementara getClassnyaman untuk mengambil informasi yang sama dari turunan jenis.

Namun, classOf[T]dan getClassmengembalikan nilai yang sedikit berbeda, yang mencerminkan efek penghapusan tipe pada JVM, dalam kasus getClass.

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

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

Itu sebabnya yang berikut ini tidak akan berfungsi :

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

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

Ada tiket tentang jenis pengembaliangetClass .

( James Moore melaporkan bahwa tiketnya "sekarang", yaitu November 2011, dua tahun kemudian, diperbaiki.
Pada 2.9.1, getClasssekarang tidak:

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

)

Kembali pada tahun 2009:

Akan bermanfaat jika Scala memperlakukan return dari getClass () sebagai java.lang.Class [T] forSome {val T: C} di mana C adalah sesuatu seperti penghapusan tipe statis dari ekspresi di mana getClass adalah dipanggil

Itu akan membiarkan saya melakukan sesuatu seperti berikut di mana saya ingin mengintrospeksi kelas tetapi tidak perlu contoh kelas.
Saya juga ingin membatasi jenis kelas yang ingin saya introspeksi, jadi saya menggunakan Kelas [_ <: Foo]. Tapi ini mencegah saya lulus di kelas Foo dengan menggunakan Foo.getClass () tanpa gips.

Catatan: mengenai getClass, solusi yang mungkin adalah:

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
VONC
sumber
4
FYI, Tiket @VonC yang disebutkan ditandai telah diperbaiki pada 22 / Jun / 11. Di 2.9.1, getClass sekarang melakukan: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = class java.lang.String
James Moore
49

classOf[Account]di Scala setara dengan Account.classdi Jawa.

Jonathan Graehl
sumber