2010-07-23 18 views
11

Digamos que tengo un objeto Java que tiene entre otros los siguientes métodos:"iteración" a través de métodos

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

¿Hay una manera de iterar a través de estos métodos y llamo como el siguiente código?

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

Gracias por sus próximas ideas.

Respuesta

8

Hay camino utilizando la reflexión:

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

Sin embargo: este negocio todos los olores de las malas prácticas de codificación! ¿No puedes volver a escribir todos los métodos getFieldN() como este?

String getField(int fieldNum) 

Está solicitando un problema creando métodos numerados. Recuerde que la reflexión es lenta y solo debe usarse cuando las llamadas a métodos basados ​​en cadenas son absolutamente esenciales para el flujo de su programa. A veces uso esta técnica para los lenguajes de scripting definidos por el usuario donde tiene que obtener un método por el nombre. Ese no es el caso en absoluto aquí, sus llamadas son de índice entero. Por lo tanto, debe mantener el número entero como un parámetro.

Si esto es código heredado y no puede cambiar esta codificación incorrecta, entonces sería mejor que cree un nuevo método getMethod(int) como se describe anteriormente para envolver los métodos existentes, que simplemente delegan los métodos numerados getMethodN().

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

Ver this guide como referencia.

+0

Supongo que olvidé mencionar que mi clase también tiene otros métodos que no quiero invocar. ¿Su código todavía haría el trabajo, entonces? –

+1

Si conoce sus firmas, podría llamarlas solo basándose en 'method.getName()' y en 'method.getParameterTypes()' –

0

Para poder seleccionar campos específicos y ordenarlos, debe especificarlos, es decir, mediante una lista de nombres de campos.

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