5

it's been quite a few months that i quite Java in favor of Python. Now i'm go back to java to project constraints. now, i'm wondering if there's a way to get all the aprameters (with values) of a functions programmatically inside the function itself.

something like this

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

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

where getpars() should return an HashMap with name,value pairs.

so from the example should be

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

is there anything like this?

EsseTi
  • 4,079
  • 5
  • 36
  • 63
  • 2
    what is the name and what is value here – PSR Jun 06 '13 at 08:20
  • 2
    What would you need that for? – jlordo Jun 06 '13 at 08:23
  • Why would you want to do this within the method itself? There cannot be - at least in your example - suddenly new arguments. – Dominik Sandjaja Jun 06 '13 at 08:23
  • i need to create an hashmap with key the name of the parameter and value the value of the parameter. – EsseTi Jun 06 '13 at 08:23
  • 1
    This looks like a XY problem. What do you **really** need to do? – fge Jun 06 '13 at 08:24
  • @DaDaDom this is a second step, where i want to have dynamic parameters. but in java i can't do that. i want to do this beacuse i don't want to do many lines of code just to create an hashmap for all the functions' parameters – EsseTi Jun 06 '13 at 08:24
  • What is the point of having it? And you can always do it yourself. I am sorry but it is missing the gist. – Jatin Jun 06 '13 at 08:25
  • 1
    Why don't you pass a Map to your function ? – user2336315 Jun 06 '13 at 08:25
  • @EsseTi: exactly: you can't do that in Java, so what's the point? ;-) And as stated in another comment/answer: reflection is the only way to achieve this. – Dominik Sandjaja Jun 06 '13 at 08:26
  • http://stackoverflow.com/questions/2237803/can-i-obtain-method-parameter-name-using-java-reflection – tbsalling Jun 06 '13 at 08:26
  • @DaDaDom that if i've 20 methods and i want JUST create a hashmap with of parameters i've to do it by hand seems really error prone to me. so i was looking if there is something similar to ** of python http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters – EsseTi Jun 06 '13 at 08:28
  • what do you need that maps for in the first place? – jlordo Jun 06 '13 at 08:29
  • Again, you are missing the point. Please tell what you actually **want to achieve**. Seasoned Java devs do without this just fine. It more and more looks like a design problem. – fge Jun 06 '13 at 08:29
  • @fge i've a function that accepts an hashmap and use it for making an api call. Now, i've functions that uses the api call function. for each of them i've to do the hashmap by hand, parameters by parameters. Plus, some operations (same api call) can have from 1 to 3 parameters, so i've to create 7 different functions to map all the cases). it's only me that found this not really smart approach? – EsseTi Jun 06 '13 at 08:34
  • OK, now this is getting somewhere. What are these "API calls"? Do they use an existing protocol (SOAP, JSON-RPC, other)? Or are they methods from another Java library? – fge Jun 06 '13 at 08:36
  • @fge are methods that i created.yet, it doesn't matter what they do. i just need to get the parameters as an hasmap or something similar to be flexible. but seems impossibile in java. so i hardcoded everything. – EsseTi Jun 06 '13 at 08:39

6 Answers6

2

Unfortunately this is impossible. The only thing you can do is to retrieve the list of parameters types of a particular method using reflection.

But there is no way to get a map with name -> value of each argument passed into the method itself.

Andremoniy
  • 34,031
  • 20
  • 135
  • 241
2

You can't get the name of the parameter, because it's no value just a name. If you wanna have the name of the parameter in your Map define a String which matches your parameter name and put it in.

Read this similar question. The accepted answer seems to have a solution for this using a third party library.

Community
  • 1
  • 1
Steve Benett
  • 12,843
  • 7
  • 59
  • 79
1

You can't get the names of the parameters dynamically, nor can you find the values in any way other than using the variable names. However, JAVA has the next best thing: variable arguments. If you want to have a dynamic number of arguments, you can declare your method as follows:

public void foo(Object... args)

When you call the method, you will call it with any number of arguments; foo(1, 2, "ABC") and foo(new File("config.dat"), new Scanner(), 88.5D) are both valid calls. Inside the function, args will be an array containing all of the parameters in order.

Just a few usage tips, though. The method declaration above is, in general, not considered good form. Usually, you can be much more specific. Think hard about whether or not you need all this flexibility, and consider using a few overloaded methods or possibly passing a HashMap to the function instead. Very rarely will you actually need to have dynamic parameters in that broad of a sense.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
1

You could use:

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

Or use a Map builder, see builder-for-hashmap.

Community
  • 1
  • 1
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • seems intresting, what's the meaning of `...` after `String`? – EsseTi Jun 06 '13 at 08:37
  • @EsseTi it is varargs parameters. Essentially, this is the same as passing a `String[]` as an argument, only nicer to write. – fge Jun 06 '13 at 08:38
  • I also have a similar use case. Did anyone find the solution ? – rvkant Dec 06 '18 at 07:38
  • @rvkant The OP actually wants a `class Params { int x, double y, String s; }`. With **JAXB** (with annotations like `XmlAttribute`) this then could become XML or JSON, which again as DOM object would work. Not really a compact solution though. – Joop Eggen Dec 06 '18 at 07:52
1

There are some hacky ways of getting the parameters values of an invoked method (But you have to understand that the parameters are unnamed, the best you can do is to get arg0.... argN).

  1. Use Proxies
  2. Aspect oriented programming (AspectJ, Spring AOP)

Let's consider the 1st approach. Say we want to log parameters before executing the method of some interface MethodParamsInterface, here you go. If you want to use these arguments in your logic - consider to implement them in InvocationHandler (or use EasyMock instead)

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);
    }
}
Vasily
  • 116
  • 1
  • 3
0
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

class Test01 {
    public int method01(int i, int j) {
        System.out.println("Original method01");
        return i + j;
    }
}

class ParameterWriter {
    public static <T> T getObject(T inp) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        ProxyFactory factory = new ProxyFactory();
        factory.setSuperclass(inp.getClass());
        factory.setFilter(
                new MethodFilter() {
                    @Override
                    public boolean isHandled(Method method) {
                        return true;
                    }
                }
        );
        MethodHandler handler = new MethodHandler() {
            @Override
            public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
                for (int i = 0; i < args.length; i++) {
                    System.out.println(proceed.getParameters()[i].getName() + ":" + args[i]);
                }
                return proceed.invoke(self, args);
            }
        };
        return (T) factory.create(new Class<?>[0], new Object[0], handler);
    }

}

public class Main {
    public static void main(String[] args) {
        try {
            Test01 test01 = ParameterWriter.getObject(new Test01());
            test01.method01(2, 3);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

output:

arg0:2
arg1:3
Original method01
Amir
  • 1,638
  • 19
  • 26