开发者

How to create annotations and get them in scala

I want to define some annotations and use them in Scala.

I looked into the source of Scala, found in scala.annotation package, there are some annotations like tailrec, switch, elidable, and so on. So I defined some annotations as them do:

class A extends StaticAnnotation

@A
class X {
    @A
    def aa() {}
}

Then I write a test:

object Main {
    def main(args: Array[String]) {
        val x = new X
        println(x.getClass.getAnnotations.length)
        x.getClas开发者_运维知识库s.getAnnotations map { println }
    }
}

It prints some strange messages:

1
@scala.reflect.ScalaSignature(bytes=u1" !1* 1!AbCaE
9"a!Q!! 1gn!!.<b    iBPE*,7
    Ii#)1oY1mC&1'G.Y(cUGCa#=S:LGO/AA!A  1mI!)

Seems I can't get the annotation aaa.A.

How can I create annotations in Scala correctly? And how to use and get them?


FWIW, you can now define scala annotation in scala 2.10 and use reflection to read them back.

Here are some examples: Reflecting Annotations in Scala 2.10


Could it have something to do with retention? I bet @tailrec is not included in the bytecode getting generated.

If I try to extend ClassfileAnnotation (in order to have runtime retention), Scala tells me that it can't be done, and it has to be done in Java:

./test.scala:1: warning: implementation restriction: subclassing Classfile does not
make your annotation visible at runtime.  If that is what
you want, you must write the annotation class in Java.
class A extends ClassfileAnnotation
      ^


I think you can only define annotations in Java now.

http://www.scala-lang.org/node/106


You can find a nice description of how annotations are to be used in Scala in Programming Scala.

So you can define or use annotations in scala. However there is at least one limitation:

Runtime retention is not quite possible. In theory you should subclass ClassFileAnnotation to achieve this, but currently scalac reports the following warning if you do it:

"implementation restriction: subclassing Classfile does not make your annotation visible at runtime. If that is what you want, you must write the annotation class in Java."

It also means that your code is fine as it is (at least as fine as it is currently possible in Scala), but the annotation is on the class only during compile time. So you could use it e.g. in compiler plugins, but you will not be able to access it runtime.


With scala 2.11.6, this works to extract values of a annotation:

case class MyAnnotationClass(id: String) extends scala.annotation.StaticAnnotation

val myAnnotatedClass: ClassSymbol = u.runtimeMirror(Thread.currentThread().getContextClassLoader).staticClass("MyAnnotatedClass")
val annotation: Option[Annotation] = myAnnotatedClass.annotations.find(_.tree.tpe =:= u.typeOf[MyAnnotationClass])
val result = annotation.flatMap { a =>
  a.tree.children.tail.collect({ case Literal(Constant(id: String)) => doSomething(id) }).headOption
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜