views:

46

answers:

4

Hi.

Let's say I've got a Java object that's got among others the following methods:

public String getField1();
public String getField2();
public String getField3();
public String getField4();
public String getField5();

Is there a way to iterate through these methods and call 'em like the following code?

String fields = "";
for(int i = 1; i <= 5; i ++){
   fields += object.(getField+i) + " | ";
}

Thank you for your upcoming ideas.

+2  A: 
Class yourClass = YourClass.class;
for (Method method : yourClass.getMethods()){
    method.invoke(obj, args);           
}

See this guide for reference.

Alberto Zaccagni
I guess I forgot to mention, that my class has other methods too that I don't want to invoke. Would your code still do the job then?
Bernhard V
If you know their signatures you could call only them basing on `method.getName()` and on `method.getParameterTypes()`
Alberto Zaccagni
A: 

you can use Java reflection.

Upul
+2  A: 

There is a way using reflection:

try{
  Method m= object.getClass().getMethod("getField"+String.valueOf(i), new Class[]{});
  fields+=(String)m.invoke(object);
}catch(...){...}

However: This business all smells of bad coding practice! Can't you rewrite all the getFieldN() methods like this?

String getField(int fieldNum)

You are asking for trouble by creating numbered methods. Remember that reflection is slow and should only be used when String-based method calls are absolutely essential to the flow of your program. I sometimes use this technique for user-defined scripting languages where you have to get a method by name. That isn't the case at all here, your calls are integer-indexed. You should therefore keep the integer as a parameter.

If this is legacy code and you are absolutely unable to change this bad coding, then you might be better off creating a new method getMethod(int) as above to wrap the existing methods, that just delegates to the numbered getMethodN() methods.

Sanjay Manohar
A: 

To be able to select specific fields and order you should specifiy them i.e. by a list of field names.

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.StringTokenizer;

public class CsvReflect {
    int a = 10;
    String b = "test";
    Date d = new Date();

    public int getA() {
        return a;
    }

    public String getB() {
        return b;
    }

    public Date getD() {
        return d;
    }

    public static String toCsv(Object obj, String fields, String separator) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        StringBuilder sb = new StringBuilder();
        StringTokenizer st = new StringTokenizer(fields,",");
        while ( st.hasMoreElements() ) {
            String field = st.nextToken();
            Method getter = obj.getClass().getMethod("get"+ field, new Class[]{});
            String val = "" + getter.invoke(obj, new Class[]{});
            sb.append( val );
            if ( st.hasMoreElements() ) {
                sb.append(separator);
            }
        }
        return sb.toString();
    }
    public static void main(String[] args) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        CsvReflect csv  = new CsvReflect();
        System.out.println( csv.toCsv( csv ,"A,B,D", "|" ));
    }
}
stacker