能否获取Scala匿名内部类型的注解?实践验证
如何通过反射获取Scala匿名内部类字段的注解
当然可以拿到!你的代码之所以失败,是因为没找对Scala匿名类反射的正确路径。让我先帮你分析问题根源,再给出能跑通的解决方案:
为啥你的代码拿不到注解?
你试的两种方式都踩了Scala匿名类反射的坑:
- 第一种方式里,你从外部类的成员中取
nested的类型签名成员,但nested的静态类型是结构类型(AnyRef { val field: Int })——这是Scala用来做类型检查的抽象描述,根本不是实际运行时匿名类的真实类型,所以结构类型的成员符号自然不会带运行时注解。 - 第二种方式中,你直接拿了匿名类的Class对象,但
members返回的成员里混了不少合成的辅助元素,而且你没精准定位到目标字段的TermSymbol,导致注解被漏掉了。
可行的解决方案
我们可以要么结合Java反射定位字段,再转成Scala反射的符号;要么直接用Scala反射精准查找目标字段。下面是修改后的代码:
object ReflectionBug { @native val outer: Int = 5 val nested = new { @native val field: Int = 4 } def main(args: Array[String]): Unit = { val mirror = scala.reflect.runtime.universe.runtimeMirror(ReflectionBug.getClass.getClassLoader) // 方法1:Java反射+Scala反射结合 val nestedCls = nested.getClass // 先用Java反射拿到目标字段 val javaField = nestedCls.getDeclaredField("field") // 把Java字段映射成Scala反射的TermSymbol val nestedSym = mirror.classSymbol(nestedCls).toType.decl(scala.reflect.runtime.universe.TermName("field")).asTerm // 现在就能拿到注解了 val annotations1 = nestedSym.annotations println(s"方法1获取的注解:$annotations1") // 会输出包含@native的注解 // 方法2:纯Scala反射精准查找 val nestedType = mirror.classSymbol(nestedCls).toType val fieldSym = nestedType.members.find(_.name == scala.reflect.runtime.universe.TermName("field")).get.asTerm val annotations2 = fieldSym.annotations println(s"方法2获取的注解:$annotations2") // 同样能拿到@native注解 } }
要注意的小细节
- Scala编译匿名类时会生成合成类(类名类似
ReflectionBug$$anon$1),你得精准找到这个类里对应字段的TermSymbol才能拿到注解,不能只靠模糊的members遍历。 - 结构类型只是静态类型检查的工具,完全不保留运行时的注解信息,必须基于实例的真实运行时类来做反射操作。
内容的提问来源于stack exchange,提问作者J Pullar
相关产品推荐
相关产品推荐

