"Итерация" с помощью методов

Скажем, у меня есть объект Java, который получил среди других следующие методы:

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

Есть ли способ выполнить итерацию этих методов и вызвать их как следующий код?

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

Спасибо за ваши идеи.

Ответ 1

Существует способ использования отражения:

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

Однако: Этот бизнес пахнет плохой практикой кодирования! Не можете ли вы переписать все методы getFieldN(), подобные этому?

String getField(int fieldNum)

Вы запрашиваете проблемы, создавая нумерованные методы. Помните, что отражение медленное и должно использоваться только тогда, когда вызовы методов на основе String абсолютно необходимы для потока вашей программы. Я иногда использую эту технику для пользовательских языков сценариев, где вам нужно получить метод по имени. Это совсем не так, ваши вызовы с индексом integer. Поэтому вы должны сохранить целое число как параметр.

Если это устаревший код, и вы абсолютно не можете изменить это плохое кодирование, вам может быть лучше создать новый метод getMethod(int), как описано выше, чтобы обернуть существующие методы, которые просто делегируют нумерованные методы getMethodN().

Ответ 2

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

См. это руководство для справки.

Ответ 3

Чтобы иметь возможность выбирать определенные поля и порядок, вы должны указать их, т.е. список имен полей.

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