Skala odpowiednika Java java.lang.Class <T> Obiekt


183

Pytanie najlepiej wyjaśnić na przykładzie:

W Javie dla menedżera JPA EntityManager mogę wykonać następujące czynności (Konto jest moją klasą Entity):

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

W Scali moja naiwna próba to:

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

Ale kiedy próbuję używać Account.classw Scali, wydaje się, że to nie lubi. Jak mogę określić obiekt java.lang.Class dla klasy konta w Scali?


VonC już dostarczył odpowiedź, ale spójrz na moje własne pytanie / odpowiedź na temat Scala & Erasure. Myślę, że może to dostarczyć pomysłów na robienie rzeczy w inny sposób niż to, czego próbujesz.
Daniel C. Sobral

Odpowiedzi:


264

Zgodnie z „ 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>

classOf[T]Metoda zwraca reprezentację środowiska wykonawczego dla typu Scala. Jest to analogiczne do wyrażenia Java T.class.
Używanie classOf[T]jest wygodne, gdy masz typ, o którym chcesz uzyskać informacje, natomiast getClassjest wygodne do pobierania tych samych informacji z wystąpienia typu.

Jednak classOf[T]i getClasspowrót nieco różne wartości, co odzwierciedla wpływ typu usunięcia w JVM w przypadku getClass.

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

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

Dlatego następujące działania nie będą działać :

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

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

Istnieje bilet dotyczący rodzaju zwrotugetClass .

( James Moore informuje, że bilet jest „teraz”, tj. Listopad 2011, dwa lata później, naprawiony.
W wersji 2.9.1 getClassteraz:

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

)

W 2009 roku:

Byłoby użyteczne, gdyby Scala traktował zwrot z getClass () jako java.lang.Class [T] forSome {val T: C}, gdzie C jest jak usunięcie statycznego typu wyrażenia, na którym getClass jest nazywa

Pozwoliłoby mi to zrobić coś takiego, gdy chcę introspekcji w klasie, ale nie powinienem potrzebować instancji klasy.
Chcę również ograniczyć rodzaje klas, na których chcę introspekcji, więc używam Class [_ <: Foo]. Ale to uniemożliwia mi przekazanie klasy Foo za pomocą Foo.getClass () bez obsady.

Uwaga: w związku getClassz możliwym obejściem byłoby:

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
Do Twojej wiadomości, wspomniany bilet @VonC został oznaczony jako naprawiony na 22 / Jun / 11. W wersji 2.9.1 getClass robi teraz: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = klasa java.lang.String
James Moore

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.