TL;DR:基本上,我正在寻找 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
Related
我想我想要的是《反思概述》在“在运行时实例化类型”部分中,但我不明白为什么我必须跳过这么多的环节才能获取注释中的值。在 Java 中,该值只是被丢弃。
问题“请参阅 Scala 反射中的注释”似乎相关,但问题来自 2011 年并且适用于 Scala 2.9。我正在使用 2.10,据我所知,从那时起,反射的工作方式发生了很大的变化。