如何通过Scala / Java方法中的反射获取参数名称和类型?

Jus12:

我们可以使用反射来获取方法名称,如下所示:

object Foo { def bar(name:String, age:Int) = {} } 
val foo = Foo.getClass
val methods = foo.getMethods.filter(_.getName.startsWith("b"))
methods.foreach(m => println(m.getName))

现在,我需要获取参数类型和名称。

  • 参数名称是否存储在字节码中?如果回答是,那么如何访问它们?
  • 如果以上回答为“否”,我们可以使用注释以某种方式存储名称吗?
  • 有人可以举一个例子来阅读类型,以及如何使用它们。我只对具有String和/或Array[String]类型参数的函数感兴趣

[编辑:]解决方案的Java版本也可以。

[编辑:]注释似乎是做到这一点的一种方法。但是,Scala注释支持不是很好。相关的SO问题

Jus12:

如果类中存在调试信息,则可以按照以下步骤进行操作。

我基本上是使用Adam Paynter的答案,在稍作修改后此处复制粘贴代码以使其在Scala中工作。

package test
import java.io.InputStream
import java.util.ArrayList
import scala.collection.JavaConversions._
import org.objectweb.asm.ClassReader
import org.objectweb.asm.Type
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.LocalVariableNode
import org.objectweb.asm.tree.MethodNode

object Util {
  case class Param(paraName:String, paraType:Type)
  case class ScalaMethod(name:String, returnType:Type, params:List[Param])

  def main(args:Array[String]):Unit = {
    getMethods(scala.util.Random.getClass).foreach(printMethod _ )
    def printMethod(m:ScalaMethod) = {
      println (m.name+" => "+m.returnType.getClassName)
      m.params.foreach(p =>
        println (" "+ p.paraName+":"+p.paraType.getClassName))
    }
  }

  /**
   * extracts the names, parameter names and parameter types of all methods of c
   */
  def getMethods(c:Class[_]):List[ScalaMethod] = {
    val cl:ClassLoader = c.getClassLoader();
    val t:Type = Type.getType(c);
    val url:String = t.getInternalName() + ".class";
    val is:InputStream = cl.getResourceAsStream(url);
    if (is == null)
      throw new IllegalArgumentException("""The class loader cannot
                                         find the bytecode that defined the
                                         class (URL: " + url + ")""");
    val cn = new ClassNode();
    val cr = new ClassReader(is);
    cr.accept(cn, 0);
    is.close();
    val methods = cn.methods.asInstanceOf[java.util.List[MethodNode]];
    var mList:List[ScalaMethod] = Nil
    if (methods.size > 0) for (i <- 1 to methods.size) {
      val m:MethodNode = methods.get(i-1)
      val argTypes:Array[Type] = Type.getArgumentTypes(m.desc);
      val paraNames = new java.util.ArrayList[String](argTypes.length)
      val vars = m.localVariables.asInstanceOf[java.util.List[LocalVariableNode]];
      var pList:List[Param] = Nil
      if (argTypes.length > 0) for (i <- 0 to argTypes.length) {
          // The first local variable actually represents the "this" object
          paraNames.add(vars.get(i).name);
          pList = Param(paraNames.get(i-1), argTypes(i-1)) :: pList
      }
      mList = ScalaMethod(m.name, Type.getReturnType(m.desc), pList) :: mList
    }
    mList
  }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何通过Kotlin中的反射获取参数名称?

如何使用Java反射获取参数名称

如何通过反射获取通用参数名称

如何通过Java中的反射获取方法参数的值?

如何使用反射获取调用方法的名称和类型?

如何获取对象的构造函数的参数名称(反射)?

(反射)在Swift中通过函数名称调用带有参数的方法

如何通过scala反射创建带有类型参数的实例?

如何通过Scala中的类方法传递类型参数?

如何在具有泛型参数和返回类型方法的Java中使用反射获取类的实例?

如何在TypeScript中为函数参数设置参数名称和类型?

Scala:在哈希图中存储参数名称和类型

通过Scala中的反射确定构造函数参数计数和类型

如何以编程方式获取 scipy 中的参数名称和值

如何获取参数名称?

如何使用Scala反射查找返回类型参数的方法的类型?

Scala如何通过模式获取LocalDate

Scala如何通过索引获取子列表

如何在反射类方法(PHP 5.x)中获取参数类型?

如何通过Scala中的参数化类型获取隐式val / def?

如何在Delphi中获取方法参数名称数组/列表?

如何避免函数名称中的参数类型?

如何在运行时获取Java中的参数名称

如何使用Java反射获取类型参数值?

如何在装饰器中获取参数名称

如何获取传递到块中的参数名称?

Java如何通过以原始类型作为参数的反射来调用方法

如何在C#中使用反射从类型和设置属性值中按名称获取属性

如何在Java中仅获取特定的返回类型和方法名称而没有完全限定的返回类型和方法名称