Как создать аннотации и получить их в 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? И как их использовать и получать?
Ответы
Ответ 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
^
Ответ 2
FWIW, теперь вы можете определить аннотацию scala в scala 2.10 и использовать отражение, чтобы прочитать их назад.
Вот несколько примеров:
http://www.veebsbraindump.com/2013/01/reflecting-annotations-in-scala-2-10/
Ответ 3
Думаю, теперь вы можете определять аннотации в Java.
http://www.scala-lang.org/node/106
Ответ 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
}