2009-07-16 7 views
156

La question est mieux expliquée par un exemple:Scala équivalent de Java java.lang.Class <T> objet

En Java pour une Assemblée parlementaire paritaire EntityManager, je peux faire ce qui suit (compte est ma classe d'entité):

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

en Scala, ma tentative naïve est:

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

Mais quand j'essaie d'utiliser Account.class à Scala, il semble pas comme ça. Comment puis-je spécifier l'objet java.lang.Class pour la classe Account dans Scala?

+0

VonC déjà fourni la réponse, mais jetez un oeil à ma [question/réponse] (http://stackoverflow.com/ questions/1094173/how-do-i-get-around-type-erasure-on-scala-ou-pourquoi-cant-i-get-le-type-paramètre) sur Scala & Erasure. Je pense que cela pourrait vous donner des idées pour faire les choses différemment de ce que vous essayez. –

Répondre

227

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

La méthode classOf[T] retourne la représentation d'exécution pour un type Scala. Il est analogue à l'expression Java T.class.
L'utilisation de classOf[T] est pratique lorsque vous avez un type sur lequel vous voulez des informations, tandis que getClass est pratique pour récupérer les mêmes informations à partir d'une instance du type.

Cependant, classOf[T] et getClass retour des valeurs légèrement différentes, ce qui reflète l'effet d'effacement de type sur la machine virtuelle Java, dans le cas de getClass.

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

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

C'est pourquoi le following will not work:

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

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

Il y a un ticket regarding the return type of getClass.

(James Moore rapporte que le billet est "maintenant", soit novembre 2011, deux ans plus tard, fixé
En 2.9.1, getClass fait maintenant.

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

)

Retour en 2009:

Il serait utile si Scala devait traiter le retour de getClass() comme java.lang.Class [T] forsome {val T: C} où C est somethin g comme l'effacement du type statique de l'expression sur laquelle getClass est appelée

Il me laisserait faire quelque chose comme ceci où je veux introspecter sur une classe mais ne devrait pas avoir besoin d'une instance de classe.
Je veux également limiter les types de classes sur lesquelles je veux introspecter, donc j'utilise la classe [_ <: Foo]. Mais cela m'empêche de passer dans une classe Foo en utilisant Foo.getClass() sans un cast.

Note: en ce qui concerne getClass, une solution de contournement possible serait la suivante:

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

FYI, Le billet @VonC mentionné a été marqué fixe le 22/Juin/11. Dans 2.9.1, getClass fait maintenant: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = classe java.lang.String –

41

classOf[Account] dans Scala est équivalent à Account.class en Java.