Equivalente en escala de Java java.lang.Class <T> Object

183

La pregunta se explica mejor con un ejemplo:

En Java para un EntityManager JPA, puedo hacer lo siguiente (La cuenta es mi clase de entidad):

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

En Scala, mi intento ingenuo es:

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

Pero cuando trato de usar Account.classen Scala, parece que no me gusta esto. ¿Cómo puedo especificar el objeto java.lang.Class para la clase Account en Scala?

Kekoa
fuente
VonC ya proporcionó la respuesta, pero eche un vistazo a mi propia pregunta / respuesta en Scala & Erasure. Creo que podría proporcionarle ideas para hacer las cosas de una manera diferente a la que está intentando.
Daniel C. Sobral

Respuestas:

264

De acuerdo con " El sistema de tipo 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>

El classOf[T]método devuelve la representación en tiempo de ejecución para un tipo Scala. Es análogo a la expresión de Java T.class.
El uso classOf[T]es conveniente cuando tiene un tipo sobre el que desea información, mientras que getClasses conveniente para recuperar la misma información de una instancia del tipo.

Sin embargo, classOf[T]y getClassdevuelve valores ligeramente diferentes, reflejando el efecto de borrado de tipo en la JVM, en el caso de getClass.

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

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

Es por eso que lo siguiente no funcionará :

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

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

Hay un billete con respecto al tipo de retornogetClass .

( James Moore informa que el boleto está "ahora", es decir, noviembre de 2011, dos años después, corregido.
En 2.9.1, getClassahora hace:

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

)

De vuelta en 2009:

Sería útil si Scala tratara el retorno de getClass () como un java.lang.Class [T] forSome {val T: C} donde C es algo así como la eliminación del tipo estático de la expresión en la que getClass es llamado

Me permitiría hacer algo como lo siguiente donde quiero introspectar en una clase pero no debería necesitar una instancia de clase.
También quiero limitar los tipos de clases en las que quiero introspectar, así que uso la Clase [_ <: Foo]. Pero esto me impide pasar a una clase de Foo usando Foo.getClass () sin un yeso.

Nota: con respecto a getClass, una posible solución sería:

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
fuente
44
Para su información, el boleto @VonC mencionado fue marcado como fijo el 22 / Jun / 11. En 2.9.1, getClass ahora hace: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = class java.lang.String
James Moore
49

classOf[Account]en Scala es equivalente a Account.classen Java.

Jonathan Graehl
fuente