如何创建注释并在scala中获取它们

时间:2011-03-03 05:28:19

标签: scala annotations

我想定义一些注释并在Scala中使用它们。

我查看了scala.annotation包中的Scala源代码,有一些注释,如tailrecswitchelidable,等等。所以我定义了一些注释:

class A extends StaticAnnotation

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

然后我写了一个测试:

object Main {
    def main(args: Array[String]) {
        val x = new X
        println(x.getClass.getAnnotations.length)
        x.getClass.getAnnotations map { println }
    }
}

它会打印一些奇怪的消息:

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!)

似乎我无法获得注释aaa.A

如何在Scala中正确创建注释?以及如何使用和获取它们?

5 个答案:

答案 0 :(得分:16)

FWIW,您现在可以在scala 2.10中定义scala注释并使用反射来读取它们。

以下是一些例子: Reflecting Annotations in Scala 2.10

答案 1 :(得分:6)

它可能与保留有关吗?我打赌@tailrec不包含在生成的字节码中。

如果我尝试扩展ClassfileAnnotation(为了保留运行时),Scala告诉我它无法完成,而且必须用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
      ^

答案 2 :(得分:3)

我认为你现在只能在Java中定义注释。

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

答案 3 :(得分:2)

您可以在Programming Scala中找到有关如何在Scala中使用注释的详细说明。

因此,您可以在scala中定义或使用注释。但至少有一个限制:

运行时保留不太可能。从理论上讲,您应该将ClassFileAnnotation子类化为实现此目的,但是如果您这样做,scalac会报告以下警告:

“实现限制:子类化Classfile不会使您的注释在运行时可见。如果这是您想要的,您必须用Java编写注释类。”

这也意味着您的代码很好(至少与Scala中当前可能的一样好),但注释仅在编译期间在类上。所以你可以使用它,例如在编译器插件中,但您将无法访问它运行时。

答案 4 :(得分:0)

使用scala 2.11.6,这可以提取注释的值:

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
}