Scala equivalente di Java java.lang.Class <T> Object


183

La domanda è meglio spiegata da un esempio:

In Java per un EntityManager JPA, posso fare quanto segue (Account è la mia classe Entity):

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

A Scala, il mio ingenuo tentativo è:

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

Ma quando provo ad usare Account.classScala, sembra che non mi piaccia. Come posso specificare l'oggetto java.lang.Class per la classe Account in Scala?


VonC ha già fornito la risposta, ma dai un'occhiata alla mia domanda / risposta su Scala & Erasure. Penso che potrebbe fornirti idee per fare le cose in modo diverso rispetto a quello che stai provando.
Daniel C. Sobral,

Risposte:


264

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

Il classOf[T]metodo restituisce la rappresentazione di runtime per un tipo di Scala. È analogo all'espressione Java T.class.
L'uso classOf[T]è utile quando si dispone di un tipo per il quale si desiderano informazioni, mentre getClassè conveniente per recuperare le stesse informazioni da un'istanza del tipo.

Tuttavia, classOf[T]e getClassrestituire valori leggermente diversi, per l'effetto di cancellazione di tipo sulla JVM, nel caso di getClass.

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

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

Ecco perché non funzionerà :

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

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

C'è un biglietto relativo al tipo di ritorno digetClass .

( James Moore riporta che il biglietto è "adesso", ovvero il novembre 2011, due anni dopo, fissato.
Nella 2.9.1, getClassora fa:

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

)

Nel 2009:

Sarebbe utile se Scala trattasse il ritorno da getClass () come java.lang.Class [T] forSome {val T: C} dove C è qualcosa come la cancellazione del tipo statico dell'espressione su cui è getClass chiamato

Mi permetterebbe di fare qualcosa di simile al seguente in cui voglio introspezione su una classe ma non dovrei aver bisogno di un'istanza di classe.
Voglio anche limitare i tipi di classi su cui voglio introspettare, quindi uso Class [_ <: Foo]. Ma questo mi impedisce di passare in una classe Foo usando Foo.getClass () senza un cast.

Nota: per quanto riguarda getClass, una possibile soluzione alternativa sarebbe:

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
Cordiali saluti, Il biglietto menzionato da @ConC è stato contrassegnato come fisso il 22 / giu / 11. In 2.9.1, getClass ora esegue: scala> "pippo" .getClass res0: java.lang.Class [_ <: java.lang.String] = class java.lang.String
James Moore,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.