【问题标题】:Getting the name of a method parameter获取方法参数的名称
【发布时间】:2011-10-09 05:56:36
【问题描述】:

Java 6 中,假设我有以下方法签名:

public void makeSandwich(Bread slice1, Bread slice2, List<Filling> fillings, boolean mustard)

我想知道在运行时传递给slice2 或任何其他参数的值,这里重要的是我想通过参数名称获取值。

我知道如何使用getParameterTypesgetGenericParameterTypes 获取参数类型列表。

理想情况下,我想获得参数列表names,而不是类型。有办法吗?

【问题讨论】:

标签: java reflection runtime java-6


【解决方案1】:

从 Java 1.8 开始,只要参数名称在类文件中,就可以做到这一点。使用javac 这是通过-parameters 标志完成的。来自javac 帮助

-parameters    Generate metadata for reflection on method parameters

您需要从 IDE 中查看编译器设置。

如果参数名称在类文件中,那么这里是一个这样做的例子

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class ParameterNamesExamples {

  public static void main(String[] args) throws Exception {
    Method theDoSomethingMethod = ExampleClass.class.getMethods()[0];
    // Now loop through the parameters printing the names
    for(Parameter parameter : theDoSomethingMethod.getParameters()) {
      System.out.println(parameter.getName());
    }
  }

  private class ExampleClass {
    public void doSomething(String myFirstParameter, String mySecondParameter) {
      // No-op
    }
  }
}

输出将取决于参数名称是否在类文件中。如果它们是输出是:

myFirstParameter
mySecondParameter

如果不是,则输出为:

arg0
arg1

有关 Oracle 的更多信息,请访问 Obtaining Names of Method Parameters

【讨论】:

    【解决方案2】:

    如果您告诉编译器包含参数名称(使用调试信息编译),则参数名称可用。 Spring 有ParameterNameDiscoverer 可以帮助您获取名称。 default implementation 使用 asm ClassReader 来做到这一点。

    对于javac,您应该包含-g 参数以包含调试信息。对于 Eclipse,我认为它是默认存在的;它可以使用首选项进行配置:Java -> Compiler,然后启用“存储有关方法参数的信息(可通过反射使用)”(另请参阅this answer)。

    一些框架使用这个。例如 spring-mvc 有 @RequestParam 如果可解析,则默认为参数名称。它还支持显式命名 - @RequestParam("foo"),以防未提供调试信息。

    【讨论】:

    【解决方案3】:

    除了this 回答: “如果您告诉编译器包含参数名称,则参数名称可用”

    如果您使用的是 Eclipse,请转到项目 -> 属性 -> Java 编译器 -> 选中“存储有关方法参数的信息(可通过反射使用)

    【讨论】:

      【解决方案4】:

      在将此问题标记为已回答后,我找到了另一种解决方案。解决方案是Paranamer

      例子:

       Method method = Foo.class.getMethod(...);
      
       Paranamer paranamer = new CachingParanamer();
      
       String[] parameterNames = paranamer.lookupParameterNames(method) // throws ParameterNamesNotFoundException if not found
      
       // or ...
      
       parameterNames = paranamer.lookupParameterNames(method, false) // will return null if not found
      

      【讨论】:

        【解决方案5】:

        您是否拥有该方法的代码?您可以注释参数并将名称作为参数@Param("slice1") 传递。稍后您将能够获取注释并从中提取参数名称。

        【讨论】:

          【解决方案6】:

          您可以简单地将参数的值分配给另一个值

          Bread slice2;
          
          public void makeSandwich(Bread slice1, Bread slice2, List<Filling> fillings, boolean mustard) {
              this.slice2 = slice2;
              System.out.println(this.slice2.getSomething());
          }
          

          【讨论】:

            【解决方案7】:

            这是不可能的。类文件不包含参数名称,当源不可用时,您可以通过 IDE 的自动完成功能看到这一点。

            因此,反射 API 无法给出参数名称。

            【讨论】:

            • 任何其他方式,即使没有反射?
            • 我建议使用包含变体的HashMap。或者,(但对我来说似乎很狡猾),看看 IDE 如何从源 JAR 中提取参数名称。
            • 您必须自己记录。
            • 不完全正确。可以包含参数名称(例如,我认为 eclipse 编译器默认会这样做)
            • “类文件不包含参数名称”。如果你也有源文件,你可能会做一些诡计。正如@kbok 所提到的,如果源可用,IDE 会在方法上显示参数名称。
            【解决方案8】:

            在 Java 中,参数名称不能通过反射获得。

            【讨论】:

              猜你喜欢
              • 2015-10-01
              • 2016-10-21
              • 2010-09-18
              • 2010-09-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多