在 Scala 中访问注释值 [英] Accessing an Annotation Value in Scala

查看:53
本文介绍了在 Scala 中访问注释值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL;DR:基本上,我正在寻找与 Java 等效的 Scala:

TL;DR: Basically, I'm looking for the Scala equivalent of the Java:

(MyAnnotation) Thing.getClass().getAnnotations()[0]

尽管我可以愉快地发现注释并根据它们的类型进行查询,但我似乎无法从 scala.reflect.runtime.universe.Annotation 进入我的实际类型.

Despite the fact that I can happily discover annotations and query based on their type, I can't seem to get from a scala.reflect.runtime.universe.Annotation into my actual type.

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() 填充数组.>

The joyous part about all this is I can't even use the traditional Java method even if I wanted, as Scala doesn't bother to populate the array from getAnnotations() anymore.

scala> Thing.getClass.getAnnotations.length
res2: Int = 0

<小时>

相关

我想我想要的是 "Reflection Overview" 在在运行时实例化类型"一节中,但我不明白为什么我必须跳过这么多圈子才能获得注释中的值.在 Java 中,该值只是一种丢弃.


Related

I think what I want is sort of in "Reflection Overview" in the section "Instantiating a Type at Runtime," but I don't see why I would have to jump through so many hoops just to get the values in an annotation. In Java, the value is just a cast away.

问题 查看 Scala 反射中的注释" 似乎相关,但问题来自 2011 年,适用于 Scala 2.9.我使用的是 2.10,据我所知,从那时起,反射的工作方式发生了很大变化.

The question "See annotations in Scala reflection" seems related, but the question is from 2011 and applies to Scala 2.9. I'm using 2.10 and from what I can tell, a huge amount of how reflection works has changed since then.

推荐答案

不是 java 等价物,但在 scala 2.11.6 中,这可以从注释中提取值:

Not the java equivalent, but with scala 2.11.6, this works to extract values out of a annotation:

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
}

我知道您可能已经这样做了,但以防万一它可以帮助某人:)

I understand that you might have done it already, but just in case it can help someone :)

这篇关于在 Scala 中访问注释值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆