简体   繁体   English

从 Java 方法获取 Scala 注释

[英]Get Scala annotation from Java Method

I have an instance of Java Method that represents a Scala function with a Scala annotation (that extends StaticAnnotation ).我有一个 Java Method实例,它表示一个带有 Scala 注释(扩展StaticAnnotation )的 Scala 函数。 I know I can use Method.getAnnotation(classOf[SomeJavaAnnotation]) to get a Java annotation, but this returns null for Scala annotations.我知道我可以使用Method.getAnnotation(classOf[SomeJavaAnnotation])来获取 Java 注释,但这对于 Scala 注释返回null

How can I get the Scala annotation from this?我怎样才能从中获得 Scala 注释? It seems I need to convert it to a Scala MethodSymbol first, but I don't see an obvious way to do that and I've only seen resources showing how to go the other way (from Scala MethodSymbol to Java Method ).似乎我需要MethodSymbol它转换为 Scala MethodSymbol ,但我没有看到明显的方法来做到这一点,我只看到了显示如何走另一条路的资源(从 Scala MethodSymbol到 Java Method )。

Scala annotations are invisible for Java reflection. Scala 注释对于 Java 反射是不可见的。

Either任何一个

  • use Java annotations (with runtime retention policy), then they will be visible for Java reflection, or使用 Java 注释(带有运行时保留策略),然后它们将在 Java 反射中可见,或者

  • use Scala reflection , it can see Scala annotations.使用Scala 反射,它可以看到 Scala 注释。


This is how java.lang.reflect.Method can be converted into scala.reflect.runtime.universe.MethodSymbol这就是如何将java.lang.reflect.Method转换为scala.reflect.runtime.universe.MethodSymbol

import java.lang.reflect.Method
import scala.reflect.runtime
import scala.reflect.runtime.universe._

def methodToMethodSymbol(method: Method): MethodSymbol = {
  val runtimeMirror = runtime.currentMirror
  val classSymbol = runtimeMirror.classSymbol(method.getDeclaringClass)
  classSymbol.typeSignature.decl(TermName(method.getName)).asMethod // (*)
}

If there are overloaded versions of the method, you'll have to replace the line (*) with如果该方法有重载版本,则必须将 (*) 行替换为

classSymbol.typeSignature.decl(TermName(method.getName)).alternatives.find(
  _.asMethod.paramLists.flatten.map(_.typeSignature.erasure.typeSymbol.asClass) == 
    method.getParameterTypes.map(runtimeMirror.classSymbol).toList
).get.asMethod

Another implementation:另一个实现:

def methodToMethodSymbol(method: Method): MethodSymbol = {
  val runtimeMirror = runtime.currentMirror
  val castedRuntimeMirror = runtimeMirror.asInstanceOf[{
    def methodToScala(meth: Method): scala.reflect.internal.Symbols#MethodSymbol
  }]

  castedRuntimeMirror.methodToScala(method).asInstanceOf[MethodSymbol]
}

Testing:测试:

class myAnnotation extends StaticAnnotation

class MyClass {
  @myAnnotation
  def myMethod(i: Int): Unit = ()
}

val clazz = classOf[MyClass]
val method = clazz.getMethod("myMethod", classOf[Int])
  
val methodSymbol = methodToMethodSymbol(method) // method myMethod
methodSymbol.annotations // List(myAnnotation)

Just in case, here is reverse conversion of scala.reflect.runtime.universe.MethodSymbol into java.lang.reflect.Method以防万一,这里是将scala.reflect.runtime.universe.MethodSymbol反向转换为java.lang.reflect.Method

def methodSymbolToMethod(methodSymbol: MethodSymbol): Method = {
  val runtimeMirror = runtime.currentMirror
  val classSymbol = methodSymbol.owner.asClass
  val clazz = runtimeMirror.runtimeClass(classSymbol)
  val paramClasses = methodSymbol.paramLists.flatten.map(paramSymbol =>
    runtimeMirror.runtimeClass(paramSymbol.typeSignature.erasure)
  )
  clazz.getMethod(methodSymbol.name.toString, paramClasses: _*)
}

Another implementation:另一个实现:

def methodSymbolToMethod(methodSymbol: MethodSymbol): Method = {
  type InternalMethodSymbol = scala.reflect.internal.Symbols#MethodSymbol
  val runtimeMirror = runtime.currentMirror
  val castedRuntimeMirror = runtimeMirror.asInstanceOf[{
    def methodToJava(sym: InternalMethodSymbol): Method
  }]

  castedRuntimeMirror.methodToJava(
    methodSymbol.asInstanceOf[InternalMethodSymbol]
  )
}

Get a java.lang.reflect.Method from a reflect.runtime.universe.MethodSymbol 从reflect.runtime.universe.MethodSymbol 获取一个java.lang.reflect.Method

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM