Еквівалент Scala Java java.lang.Class <T> Об'єкт


183

Найкраще питання пояснюється прикладом:

У Java для JPA EntityManager я можу зробити наступне (Обліковий запис - мій клас Entity):

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

У Скалі моя наївна спроба:

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

Але коли я намагаюся використовувати Account.classв Scala, мені здається, це не подобається. Як я можу вказати об’єкт java.lang.Class для класу Account в Scala?


VonC вже надав відповідь, але погляньте на моє власне питання / відповідь на Scala & Erasure. Я думаю, що це може дати вам ідеї робити речі іншими способами, ніж те, що ви намагаєтесь.
Даніель К. Собрал

Відповіді:


264

Відповідно до " Системи типу 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>

classOf[T]Метод повертає подання у час виконання для типу Scala. Це аналог виразу Java T.class.
Використання classOf[T]зручно, коли у вас є тип, про який ви хочете отримати інформацію, а getClassзручно для отримання тієї ж інформації з екземпляра цього типу.

Однак classOf[T]і getClassповерніть трохи інші значення, що відображають вплив стирання типу на JVM, у випадку getClass.

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

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

Ось чому наступне не буде працювати :

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

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

Існує квиток щодо типу поверненняgetClass .

( Джеймс Мур повідомляє, що квиток було "зараз", тобто листопад 2011 року, через два роки, зафіксовано.
У 2.9.1 getClassтепер:

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

)

Ще в 2009 році:

Було б корисно, якби Scala трактувала повернення з getClass () як java.lang.Class [T] forSome {val T: C}, де C - це щось на зразок стирання статичного типу виразу, на якому getClass є називається

Це дозволило б мені зробити щось на кшталт наступного, де я хочу представити клас, але мені не потрібен екземпляр класу.
Я також хочу обмежити типи класів, на які я хочу вступити, тому я використовую Class [_ <: Foo]. Але це заважає мені перейти до класу Foo, використовуючи Foo.getClass () без виступу.

Примітка. Щодо getClassможливого рішення:

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, згаданий квиток @VonC був позначений фіксованим 22 / червня / 11. У 2.9.1 тепер getClass робить: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = клас java.lang.String
Джеймс Мур

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.