Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 298898

Get class of Scala object for annotation

I have a use case where I need to do some Java reflection on some Scala objects (don't even ask). Anyway, I sometimes need to add these objects to an annotation, in Scala.

Here's my (java) annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
   Class<?>[] value();
}

And let's say this is my Scala object:

object Foo{}

In Java, I can reference Foo using my above annotation like this:

@MyAnnotation(Foo.class)
class SomeClass{}

In Scala, however, I don't see how I can get a type literal from an Object:

@MyAnnotation(Array(classOf[Foo]))
class SomeClass{}

This fails, with error message:

not found: type Foo

Is there any way I can reference my Foo object type in a Java annotation? Note that I can't use Foo.getClass, because that's a method call, not a constant.

Upvotes: 1

Views: 313

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51658

Try

@MyAnnotation(Array(classOf[Foo.type]))
class SomeClass

classOf[Foo.type] is allowed since Scala 2.13.4

https://github.com/scala/scala/pull/9279

https://github.com/scala/bug/issues/2453


In older Scala you can create a class literal manually using a whitebox macro

def moduleClassOf[T <: Singleton]: Class[T] = macro impl[T]

def impl[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
  import c.universe._
  Literal(Constant(weakTypeOf[T]))
}

Usage:

@MyAnnotation(Array(moduleClassOf[Foo.type]))
class SomeClass

https://gist.github.com/DmytroMitin/e87ac170d107093a9b9faf2fd4046bd5

Upvotes: 2

Related Questions