考虑以下代码:
object Foo{def foo(a:Int):List[(String, Int)] = ???}
class Bar{def bar(a:Int, b:Any):Option[(String, Long)] = ???}
给定对象或类,我需要先找到方法名(似乎没有那么难)。
之后,对于每个方法,我想找到 Scala 返回类型(不是 Java 返回类型)的字符串描述。因此,例如,对于 Foo.foo
,我需要 String List[(String, Int)]
,对于 Bar.bar
,我将需要 String Option[(String, Long)]
。
编辑:这是我根据评论尝试的:
class RetTypeFinder(obj:AnyRef) {
import scala.reflect.runtime.{universe => ru}
val m = ru.runtimeMirror(getClass.getClassLoader)
val im = m.reflect(obj)
def getRetType(methodName:String) = {
ru.typeOf[obj.type].declaration(ru.TermName(methodName)).asMethod.returnType
}
}
object A { def foo(a:Int):String = ??? } // define dummy object
class B { def bar(a:Int):String = ??? } // define dummy class
val a = new RetTypeFinder(A)
a.getRetType("foo") // exception here
val b = new RetTypeFinder(new B)
b.getRetType("bar") // exception here
我得到的错误是:
scala.ScalaReflectionException: <none> is not a method
at scala.reflect.api.Symbols$SymbolApi$class.asMethod(Symbols.scala:228)
at scala.reflect.internal.Symbols$SymbolContextApiImpl.asMethod(Symbols.scala:84)
at cs.reflect.Test.getRetCls(Test.scala:11)
...
然而,这有效(在 REPL 中试过):
import scala.reflect.runtime.{universe => ru}
val m = ru.runtimeMirror(getClass.getClassLoader)
object A { def foo(a:Int):String = ??? } // define dummy object
val im = m.reflect(A)
ru.typeOf[A.type].declaration(ru.TermName("foo")).asMethod.returnType
class B { def bar(a:Int):String = ??? } // define dummy class
val im = m.reflect(new B)
ru.typeOf[B].declaration(ru.TermName("bar")).asMethod.returnType
我需要以第一种方式使用它,我事先不知道将传递哪些对象/类。任何帮助将不胜感激。
最佳答案
一旦有了 universe.Type
,您就可以使用注释中的方法来获取其方法之一的返回类型:
import scala.reflect.runtime.{universe => ru}
def getRetTypeOfMethod(tpe: ru.Type)(methodName: String) =
tpe.member(ru.TermName(methodName)).asMethod.returnType
要获取 universe.Type
,最简单的方法是在隐式 TypeTag
中捕获:
class RetTypeFinder[T <: AnyRef](obj: T)(implicit tag: ru.TypeTag[T]) {
def getRetType(methodName: String) = {
val tpe = tag.tpe
getRetTypeOfMethod(tpe)(methodName)
}
}
但是如果你没有TypeTag
,只是一个AnyRef
类型的对象,你可以通过一个镜像
来反射(reflect)它。由于 Java 的类型删除,生成的 Type
将丢失一些信息,但它仍然足以通过名称获取方法的返回类型,因为 JVM 反射支持:
class RetTypeFinder2(obj: AnyRef) {
def getRetType(methodName: String) = {
val mirror = ru.runtimeMirror(getClass.getClassLoader)
val tpe = mirror.reflect(obj).symbol.info
getRetTypeOfMethod(tpe)(methodName)
}
}
这两种方法都能很好地解决您的问题:
scala> new RetTypeFinder(A).getRetType("foo")
res0: reflect.runtime.universe.Type = String
scala> new RetTypeFinder2(A).getRetType("foo")
res1: reflect.runtime.universe.Type = String
scala> new RetTypeFinder(new B).getRetType("bar")
res2: reflect.runtime.universe.Type = String
scala> new RetTypeFinder2(new B).getRetType("bar")
res3: reflect.runtime.universe.Type = String
关于scala - 如何使用 Scala 反射获取方法的返回类型字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38947338/