187

The question is best explained by an example:

In Java for a JPA EntityManager, I can do the following(Account is my Entity class):

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

In Scala, my naive attempt is:

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

But when I try to use Account.class in Scala, it seems to not like this. How can I specify the java.lang.Class object for the Account class in Scala?

Kekoa
  • 27,892
  • 14
  • 72
  • 91
  • VonC already provided the answer, but take a look at my own [question/answer](http://stackoverflow.com/questions/1094173/how-do-i-get-around-type-erasure-on-scala-or-why-cant-i-get-the-type-parameter) on Scala & Erasure. I think it might provide you with ideas to do things in a different way than what you are trying. – Daniel C. Sobral Jul 16 '09 at 12:30
  • https://stackoverflow.com/questions/68914075 – Dmytro Mitin Apr 08 '23 at 08:35

2 Answers2

271

According to "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>

The classOf[T] method returns the runtime representation for a Scala type. It is analogous to the Java expression T.class.
Using classOf[T] is convenient when you have a type that you want information about, while getClass is convenient for retrieving the same information from an instance of the type.

However, classOf[T] and getClass return slightly different values, reflecting the effect of type erasure on the JVM, in the case of getClass.

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

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

That is why the 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

There is a ticket regarding the return type of getClass.

(James Moore reports that the ticket is "now", ie Nov. 2011, two years later, fixed.
In 2.9.1, getClass now does:

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

)

Back in 2009:

It would be useful if Scala were to treat the return from getClass() as a java.lang.Class[T] forSome { val T : C } where C is something like the erasure of the static type of the expression on which getClass is called

It would let me do something like the following where I want to introspect on a class but shouldn't need a class instance.
I also want to limit the types of classes I want to introspect on, so I use Class[_ <: Foo]. But this prevents me from passing in a Foo class by using Foo.getClass() without a cast.

Note: regarding getClass, a possible workaround would be:

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
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 4
    FYI, The ticket @VonC mentioned was marked fixed on 22/Jun/11. In 2.9.1, getClass now does: scala> "foo".getClass res0: java.lang.Class[_ <: java.lang.String] = class java.lang.String – James Moore Nov 09 '11 at 23:03
51

classOf[Account] in Scala is equivalent to Account.class in Java.

Anubian Noob
  • 13,426
  • 6
  • 53
  • 75
Jonathan Graehl
  • 9,182
  • 36
  • 40