Scala equivalente ao objeto Java java.lang.Class <T>

183

A questão é melhor explicada por um exemplo:

Em Java para um JPA EntityManager, posso fazer o seguinte (Conta é minha classe de entidade):

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

Em Scala, minha tentativa ingênua é:

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

Mas quando tento usar Account.classno Scala, parece não gostar disso. Como posso especificar o objeto java.lang.Class para a classe Account no Scala?

Kekoa
fonte
O VonC já forneceu a resposta, mas dê uma olhada na minha própria pergunta / resposta no Scala & Erasure. Eu acho que isso pode lhe fornecer idéias para fazer as coisas de uma maneira diferente da que você está tentando.
1813 Daniel C. Sobral

Respostas:

264

De acordo com " 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>

O classOf[T]método retorna a representação de tempo de execução para um tipo Scala. É análogo à expressão Java T.class.
O uso classOf[T]é conveniente quando você tem um tipo sobre o qual deseja obter informações, enquanto getClassé conveniente recuperar as mesmas informações de uma instância do tipo.

No entanto, classOf[T]e getClassretorne valores ligeiramente diferentes, refletindo o efeito de apagamento de tipo na JVM, no caso de getClass.

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

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

É por isso que o seguinte não funcionará :

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

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

Existe um ticket referente ao tipo de retornogetClass .

( James Moore relata que o ticket é "agora", ou seja, novembro de 2011, dois anos depois, foi corrigido.
Na 2.9.1, getClassagora:

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

)

Em 2009:

Seria útil se Scala tratasse o retorno de getClass () como um java.lang.Class [T] forSome {val T: C} em que C é algo como o apagamento do tipo estático da expressão na qual getClass é chamado

Permitiria que eu fizesse algo como o seguinte, onde quero examinar uma classe, mas não deve precisar de uma instância de classe.
Também quero limitar os tipos de classes nas quais quero examinar, então uso Classe [_ <: Foo]. Mas isso me impede de passar em uma classe Foo usando Foo.getClass () sem conversão.

Nota: em relação a getClass, uma possível solução alternativa seria:

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
fonte
4
Para sua informação, o bilhete @VonC mencionado foi marcado como fixo em 22 / jun / 11. No 2.9.1, o getClass agora faz: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = classe java.lang.String
James Moore
49

classOf[Account]em Scala é equivalente a Account.classem Java.

Jonathan Graehl
fonte