2010-07-23 16 views
11

Lassen Sie uns sagen, dass ich ein Java-Objekt haben, die unter anderem folgende Methoden bekam ist:„iterieren“ durch Methoden

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

Gibt es einen Weg durch diese Methoden zu durchlaufen und rufen ‚em wie der folgende Code?

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

Vielen Dank für Ihre bevorstehenden Ideen.

Antwort

8

Es gibt einen Weg mit Reflexion:

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

jedoch: Dieses Geschäft alle Gerüche von schlechter Codierung der Praxis! Kannst du nicht alle getFieldN() Methoden so umschreiben?

String getField(int fieldNum) 

Sie bitten um Probleme, indem Sie nummerierte Methoden erstellen. Denken Sie daran, dass die Reflektion langsam ist und nur verwendet werden sollte, wenn String-basierte Methodenaufrufe für den Ablauf Ihres Programms unbedingt erforderlich sind. Ich benutze diese Technik manchmal für benutzerdefinierte Skriptsprachen, wo Sie eine Methode von Name erhalten müssen. Das ist hier überhaupt nicht der Fall, Ihre Anrufe sind integer-indexed. Sie sollten daher die ganze Zahl als Parameter beibehalten.

Wenn dieser Legacy-Code ist, und Sie sind absolut nicht in der Lage, diese schlechte Codierung zu ändern, dann könnten Sie eine neue Methode zu schaffen getMethod(int) wie oben besser dran, die bestehenden Methoden zu wickeln, dass nur die Delegierten auf die nummerierten getMethodN() Methoden.

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

Siehe this guide als Referenz.

+0

Ich denke, ich habe vergessen zu erwähnen, dass meine Klasse auch andere Methoden hat, die ich nicht aufrufen möchte. Würde Ihr Code dann immer noch funktionieren? –

+1

Wenn Sie ihre Signaturen kennen, können Sie sie nur auf Basis von 'method.getName()' und 'method.getParameterTypes()' aufrufen –

0

Um bestimmte Felder und Reihenfolge auswählen zu können, sollten Sie sie angeben, d. H. Durch eine Liste von Feldnamen.

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