4

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

像这样的东西

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

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

wheregetpars()应该返回一个HashMapwithname,value对。

所以从这个例子应该是

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

有这样的吗?

4

5 回答 5

2

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

但是没有办法通过name->获取value传递给方法本身的每个参数的映射。

于 2013-06-06T08:24:57.650 回答
2

您无法获取参数的名称,因为它只是一个名称没有价值。如果您想在 Map 中使用参数的名称,请定义一个与您的参数名称匹配的字符串并将其放入。

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

于 2013-06-06T08:25:44.933 回答
1

你可以使用:

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");

或使用 Map builder,请参阅builder-for-hashmap

于 2013-06-06T08:34:49.820 回答
1

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

public void foo(Object... args)

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

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

于 2013-06-06T08:30:20.160 回答
0

有一些获取被调用方法的参数值的 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);
    }
}
于 2013-06-06T09:00:07.023 回答