从 Java 方法获取 Scala 注释
Get Scala annotation from Java Method
我有一个 Java Method
的实例,它表示带有 Scala 注释的 Scala 函数(扩展 StaticAnnotation
)。我知道我可以使用 Method.getAnnotation(classOf[SomeJavaAnnotation])
来获得 Java 注释,但是这个 returns null
用于 Scala 注释。
如何从中获取 Scala 注释?看来我需要先将它转换为 Scala MethodSymbol
,但我没有看到一个明显的方法来做到这一点,我只看到资源显示如何走另一条路(来自 Scala MethodSymbol
到 Java Method
).
Scala 注释对于 Java 反射是不可见的。
两者都
使用 Java 注释(具有运行时保留策略),然后它们将对 Java 反射可见,或者
使用Scala reflection,可以看到Scala注解
这就是 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 // (*)
}
如果该方法有重载版本,您将不得不替换
行 (*)
与
classSymbol.typeSignature.decl(TermName(method.getName)).alternatives.find(
_.asMethod.paramLists.flatten.map(_.typeSignature.erasure.typeSymbol.asClass) ==
method.getParameterTypes.map(runtimeMirror.classSymbol).toList
).get.asMethod
另一个实现:
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]
}
测试:
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)
为了以防万一,这里把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: _*)
}
另一个实现:
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
我有一个 Java Method
的实例,它表示带有 Scala 注释的 Scala 函数(扩展 StaticAnnotation
)。我知道我可以使用 Method.getAnnotation(classOf[SomeJavaAnnotation])
来获得 Java 注释,但是这个 returns null
用于 Scala 注释。
如何从中获取 Scala 注释?看来我需要先将它转换为 Scala MethodSymbol
,但我没有看到一个明显的方法来做到这一点,我只看到资源显示如何走另一条路(来自 Scala MethodSymbol
到 Java Method
).
Scala 注释对于 Java 反射是不可见的。
两者都
使用 Java 注释(具有运行时保留策略),然后它们将对 Java 反射可见,或者
使用Scala reflection,可以看到Scala注解
这就是 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 // (*)
}
如果该方法有重载版本,您将不得不替换 行 (*) 与
classSymbol.typeSignature.decl(TermName(method.getName)).alternatives.find(
_.asMethod.paramLists.flatten.map(_.typeSignature.erasure.typeSymbol.asClass) ==
method.getParameterTypes.map(runtimeMirror.classSymbol).toList
).get.asMethod
另一个实现:
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]
}
测试:
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)
为了以防万一,这里把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: _*)
}
另一个实现:
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