TL; DR: В принципе, я ищу эквивалент Scala на Java:Доступ к аннотациям значения в Scala
(MyAnnotation) Thing.getClass().getAnnotations()[0]
Несмотря на то, что я могу с радостью обнаружить аннотации и запрос на основе их типа, я не могу получить от scala.reflect.runtime.universe.Annotation
в мой фактический тип.
scala> // Declare an annotation (it seems StaticAnnotation means runtime
scala> // retention)
scala> case class MyAnnotation(x: Int, y: String) extends scala.annotation.StaticAnnotation
defined class MyAnnotation
scala> // Make a thing decorated with MyAnnotation
scala> @MyAnnotation(x=5, y="cool") case class Thing()
defined class Thing
scala> // Look at the annotation on the Thing...the runtime clearly
scala> // understands the values on it
scala> val annotation = scala.reflect.runtime.universe.typeOf[Thing].typeSymbol.asClass.annotations(0)
annotation: reflect.runtime.universe.Annotation = MyAnnotation(5, "cool")
scala> // I can sort of get at the values by index, which isn't terribly
scala> // safe
scala> annotation.scalaArgs(0)
res0: reflect.runtime.universe.Tree = 5
scala> // And what is a Tree here anyway? It certainly isn't a String (or
scala> // Int). I just want the value!
scala> annotation.scalaArgs(1)
res1: reflect.runtime.universe.Tree = "cool"
scala> // But how do I get at those values programatically?
scala> annotation.asInstanceOf[MyAnnotation]
java.lang.ClassCastException: scala.reflect.internal.AnnotationInfos$CompleteAnnotationInfo cannot be cast to MyAnnotation
at .<init>(<console>:13)
at .<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983)
at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568)
at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:760)
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:805)
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:717)
at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:581)
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:588)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:591)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:882)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837)
at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:837)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:83)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Радостная часть обо всем этом, я не могу даже использовать традиционный метод Java, даже если я хотел, так как Scala не удосужилась заполнить массив из getAnnotations()
больше.
scala> Thing.getClass.getAnnotations.length
res2: Int = 0
эту же тему
Я думаю, что я хочу, это своего рода в "Reflection Overview" в разделе «инстанцировании типа во время выполнения», но я не понимаю, почему я должен прыгать через так много обручей, чтобы получить значения в аннотации. В Java значение просто отброшено.
Вопрос "See annotations in Scala reflection" кажется связанным, но вопрос с 2011 года относится к Scala 2.9. Я использую 2.10, и из того, что я могу сказать, с тех пор изменилось огромное количество отражений.
Спасибо за информацию. Я предполагаю, что обходным пути здесь является определение '@ interface' в Java и переход оттуда. Позор ... новые атрибуты Scala выглядят намного мощнее, чем их Java-аналоги. –
Ну, если вам нравятся аннотации Scala больше, чем Java, возможно, вам будет интересно написать Annotation.eval самостоятельно? Это не должно быть очень сложным для случая постоянных аргументов. –
Я бы с удовольствием, но для этого потребуется навык Scala, который превосходит мой собственный :-) –