[英]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.