Подтвердить что ты не робот

Как создать аннотации и получить их в scala

Я хочу определить некоторые аннотации и использовать их в Scala.

Я посмотрел на источник Scala, найденный в пакете scala.annotation, есть такие аннотации, как tailrec, switch, elidable и т.д. Поэтому я определил некоторые аннотации, как они это делают:

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? И как их использовать и получать?

4b9b3361

Ответ 1

Может ли это иметь какое-то отношение к удержанию? Я уверен, @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
      ^

Ответ 4

Вы можете найти хорошее описание того, как аннотации должны использоваться в Scala в Программирование Scala.

Таким образом, вы можете определять или использовать аннотации в scala. Однако существует хотя бы одно ограничение:

Сохранение времени выполнения не представляется возможным. Теоретически вы должны подклассифицировать ClassFileAnnotation для достижения этого, но в настоящее время scalac сообщает следующее предупреждение, если вы это сделаете:

": подклассификация Classfile не делает вашу аннотацию видимой во время выполнения. Если это то, что вы хотите, вы должны написать класс аннотации в Java."

Это также означает, что ваш код в порядке, насколько это возможно (по крайней мере, настолько, насколько это возможно в настоящее время в Scala), но аннотация находится в классе только во время компиляции. Таким образом, вы можете использовать его, например. в плагинах компилятора, но вы не сможете получить доступ к нему во время выполнения.

Ответ 5

С 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
}