Scala-Äquivalent zum Java-Objekt java.lang.Class <T>

183

Die Frage lässt sich am besten anhand eines Beispiels erklären:

In Java für einen JPA EntityManager kann ich Folgendes tun (Konto ist meine Entitätsklasse):

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

In Scala ist mein naiver Versuch:

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

Aber wenn ich versuche, es Account.classin Scala zu verwenden, scheint es mir nicht zu gefallen. Wie kann ich das Objekt java.lang.Class für die Account-Klasse in Scala angeben?

Kekoa
quelle
VonC hat die Antwort bereits gegeben, aber werfen Sie einen Blick auf meine eigene Frage / Antwort zu Scala & Erasure. Ich denke, es könnte Ihnen Ideen geben, Dinge anders zu machen als Sie es versuchen.
Daniel C. Sobral

Antworten:

263

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

Die classOf[T]Methode gibt die Laufzeitdarstellung für einen Scala-Typ zurück. Es ist analog zum Java-Ausdruck T.class.
Die Verwendung classOf[T]ist praktisch, wenn Sie einen Typ haben, zu dem Sie Informationen wünschen, und getClasspraktisch, um dieselben Informationen aus einer Instanz des Typs abzurufen.

Jedoch classOf[T]und getClassleicht unterschiedliche Werte zurück, was auf die Wirkung von Typ Löschung auf der JVM, im Fall von getClass.

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

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

Deshalb funktioniert Folgendes nicht :

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

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

Es gibt ein Ticket für die Rücksendung vongetClass .

( James Moore berichtet, dass das Ticket "jetzt", dh im November 2011, zwei Jahre später, festgelegt ist.
In 2.9.1 gilt getClassjetzt:

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

)

Zurück im Jahr 2009:

Es wäre nützlich, wenn Scala die Rückgabe von getClass () als java.lang.Class [T] für einige {val T: C} behandeln würde, wobei C so etwas wie das Löschen des statischen Typs des Ausdrucks ist, auf dem sich getClass befindet namens

Es würde mich so etwas wie das Folgende tun lassen, wo ich eine Klasse introspektieren möchte, aber keine Klasseninstanz benötigen sollte.
Ich möchte auch die Arten von Klassen einschränken, auf die ich nachdenken möchte, also verwende ich Klasse [_ <: Foo]. Dies hindert mich jedoch daran, eine Foo-Klasse zu übergeben, indem ich Foo.getClass () ohne Besetzung verwende.

Hinweis: getClassEine mögliche Problemumgehung wäre:

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
quelle
4
Zu Ihrer Information, das erwähnte Ticket @VonC wurde am 22. Juni 11 als fest markiert markiert. In 2.9.1 führt getClass jetzt Folgendes aus: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = Klasse java.lang.String
James Moore
49

classOf[Account]in Scala entspricht Account.classin Java.

Jonathan Graehl
quelle