【问题标题】:Programmatically retrive parameters and values of a method以编程方式检索方法的参数和值
【发布时间】:2013-06-02 03:54:31
【问题描述】:

已经有好几个月了,我相当 Java 支持 Python。现在我要回到java来项目约束。 现在,我想知道是否有一种方法可以在函数本身内以编程方式获取函数的所有参数(带有值)。

类似的东西

public void foo(String arg1,String arg2, Integer arg3){
... pars = ...getpars();  
}

foo("abc","dfg",123);

getpars() 应该返回一个 HashMapname,value 对。

所以从例子中应该是

arg1,"abc"
arg2,"dfg"
arg3,123

有这样的吗?

【问题讨论】:

  • 这里的名字和价值是什么
  • 你需要这个做什么?
  • 我已经编辑了问题
  • 这看起来像是一个 XY 问题。您真正需要做什么?
  • 为什么不将 Map 传递给您的函数?

标签: java methods parameters


【解决方案1】:

有一些获取被调用方法的参数值的 hacky 方法(但你必须了解参数是未命名的,你能做的最好的就是获取 arg0.... argN)。

  1. 使用代理
  2. 面向方面的编程(AspectJ、Spring AOP)

让我们考虑第一种方法。假设我们要在执行某个接口 MethodParamsInterface 的方法之前记录参数,就这样吧。如果您想在逻辑中使用这些参数 - 考虑在 InvocationHandler 中实现它们(或改用 EasyMock)

interface MethodParamsInterface {
    void simpleMethod(int parm1, int parm2);
    void simpleMethod(int parm1, int parm2, int param3);
}

public class MethodParams implements MethodParamsInterface {
    public void simpleMethod(int parm1, int parm2) {
        //business logic to be put there
    }

    public void simpleMethod(int parm1, int parm2, int param3) {
        //business logic to be put there
    }

    public MethodParamsInterface wrappedInstance() throws Exception {
        Class<?> proxyClass = Proxy.getProxyClass(MethodParams.class.getClassLoader(), MethodParamsInterface.class);
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Map<String, Object> params = new LinkedHashMap<String, Object>(args.length);
                for (int i = 0; i < args.length; i++)
                    params.put("arg" + i, args[i]);


                //printing out the parameters:
                for (Map.Entry<String, Object> paramValue : params.entrySet()) {
                    System.out.println(paramValue.getKey() + " : " + paramValue.getValue());
                }

                return MethodParams.this.getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(MethodParams.this, args);
            }
        };
        return (MethodParamsInterface) proxyClass.getConstructor(new Class[]{InvocationHandler.class}).newInstance(invocationHandler);
    }


    public static void main(String[] args) throws Exception {
        MethodParams instance = new MethodParams();
        MethodParamsInterface wrapped = instance.wrappedInstance();

        System.out.println("First method call: ");

        wrapped.simpleMethod(10, 20);

        System.out.println("Another method call: ");

        wrapped.simpleMethod(10, 20, 30);
    }
}

【讨论】:

    【解决方案2】:

    你可以使用:

    void foo(String... args) {
        for (String arg: args) { }
        for (int i = 0; i < args.length - 1; i += 2) {
            map.put(args[i], args[i + 1];
        }
    }
    
    foo("a", "1", "b", "2");
    

    或使用地图生成器,请参阅builder-for-hashmap

    【讨论】:

    • 好像很有意思,...后面的String是什么意思?
    • @EsseTi 它是可变参数。本质上,这与将 String[] 作为参数传递相同,只是写起来更好。
    • 我也有类似的用例。有人找到解决方案了吗?
    • @rvkant OP 实际上想要一个class Params { int x, double y, String s; }。使用 JAXB(带有 XmlAttribute 之类的注释),这可以变成 XML 或 JSON,这又可以作为 DOM 对象工作。虽然不是一个真正紧凑的解决方案。
    【解决方案3】:

    你不能得到参数的名字,因为它只是一个名字没有价值。如果您想在 Map 中定义参数名称,请定义一个与您的参数名称匹配的字符串并将其放入。

    阅读this 类似的问题。接受的答案似乎有一个使用第三方库的解决方案。

    【讨论】:

      【解决方案4】:

      您无法动态获取参数的名称,也无法通过使用变量名称以外的任何方式找到值。然而,JAVA 有下一个最好的东西:可变参数。如果你想有一个动态数量的参数,你可以声明你的方法如下:

      public void foo(Object... args)
      

      当你调用方法时,你会用任意数量的参数调用它; foo(1, 2, "ABC")foo(new File("config.dat"), new Scanner(), 88.5D) 都是有效调用。在函数内部,args 将是一个按顺序包含所有参数的数组。

      不过,只是一些使用技巧。上面的方法声明通常不被认为是好的形式。通常,您可以更具体。仔细考虑您是否需要所有这些灵活性,并考虑使用一些重载方法或可能将HashMap 传递给函数。您实际上很少需要具有广义上的动态参数。

      【讨论】:

        【解决方案5】:

        不幸的是,这是不可能的。您唯一能做的就是使用reflection 检索特定方法的参数类型列表。

        但是没有办法获得带有name -> value 的映射,每个参数传递到方法本身。

        【讨论】:

        • 在Java中使用代理或方面实际上是可能的
        猜你喜欢
        • 2012-07-04
        • 1970-01-01
        • 1970-01-01
        • 2014-11-04
        • 1970-01-01
        • 2012-01-30
        • 2014-02-07
        • 2010-11-04
        • 2018-07-21
        相关资源
        最近更新 更多