2016-04-30 17 views
2

Bei der Arbeit müssen wir einen Bericht für unseren Kunden generieren, der seine Parameter mehrmals während der Woche ändert. Dieser Bericht wird aus einer einzelnen Tabelle in unserer Datenbank generiert. Stellen Sie sich zum Beispiel eine Tabelle mit 100 Spalten vor, und ich muss heute einen Bericht mit nur 5 Spalten erstellen, aber morgen muss ich mit 95 Spalten generieren. In diesem Sinne habe ich eine TO-Klasse mit allen Spalten der angegebenen Tabelle erstellt und meine Abfrage gibt alle Spalten zurück (SELECT * FROM TABLE).Methoden dynamisch auf Java aufrufen

Was ich versuche zu erstellen, ist ein dynamisches Formular, um den Bericht zu generieren. Ich dachte zuerst über einen einfachen Rahmen mit einer Liste der Spalten als Kontrollkästchen angezeigt, und der Benutzer würde die Spalten auswählen, die er will (natürlich mit einer Schaltfläche auf Alles auswählen und eine andere auf Auswahl aufheben).

Wie alle Spalten den gleichen Namen wie die Attribute der Klasse TO haben, entwickelte ich den folgenden Code (Ich habe Google diese):

Class c = Test.class; 

for(int i = 0; i < listOfAttributes.length; i++) 
{ 
    auxText += String.valueOf(c.getMethod("get" + listOfAttributes[i]).invoke(this, null)); 
} 

Ist dies der bessere Weg zu tun, was ich brauche zu?

Vielen Dank im Voraus.

Obs .: Die Getter der TO-Klasse haben das Muster "getAttribute_Name".

Hinweis: Diese Frage unterscheidet sich von der Frage, bei der der Benutzer fragt, wie eine Methode mit einem bestimmten Namen aufgerufen werden soll. Ich weiß, wie das geht. Ich frage, ob dies der bessere Weg ist, das von mir beschriebene Problem zu lösen.

+1

Mögliche Duplikat [Wie rufe ich eine Java-Methode wenn der Methodenname als String angegeben wurde?] (http://stackoverflow.com/questions/160970/how-doi-i-voke-a-java-method-when-given-the-method-name-as-a -string) –

+0

Wie ich auf der Anmerkung sagte: Diese Frage unterscheidet sich von der, wo der Benutzer fragt, wie man eine Methode anruft, die einen bestimmten Namen gegeben wird. Ich weiß, wie das geht. Ich frage, ob dies der bessere Weg ist, das von mir beschriebene Problem zu lösen. –

+0

Okay. Ich werde das zurücknehmen. Ich werde feststellen, dass Ihre Notiz nach der ersten Überprüfung hinzugefügt wurde. –

Antwort

0

Mein Java ist ein wenig begrenzter, aber ich glaube, das ist ungefähr so ​​gut, wie Sie es mit Reflektion bekommen.

Class<?> c = Test.class; 

for (String attribute : listOfAttributes) { 
    auxText += String.valueOf(c.getMethod("get" + attribute).invoke(this, null)); 
} 

Da aber das klingt wie es aus möglicherweise nicht vertrauenswürdigen Daten ist, würde ich einen HashMap in diesem Fall empfehlen die Verwendung mit jeder explizit verwiesen Verfahren. Zunächst wird explizit angegeben, welche Methoden dynamisch aufgerufen werden können. Zweitens ist es typensicherer und Fehler bei der Kompilierung sind viel besser als Laufzeitfehler. Drittens ist es wahrscheinlich schneller, da es die Reflexion insgesamt vermeidet. Etwas auf die Wirkung dieses:

private static final HashMap<String, Supplier<Object>> methods = new HashMap<>(); 

// Initialize all the methods. 
static { 
    methods.set("Foo", Test::getFoo); 
    methods.set("Bar", Test::getBar); 
    // etc. 
} 

private String invokeGetter(String name) { 
    if (methods.containsKey(name)) { 
     return String.valueOf(methods.get(name).get()); 
    } else { 
     throw new NoSuchMethodException(); 
    } 
} 

Es ist wie eine große DRY Verletzung klingen könnte dies zu tun, aber die Wiederholung zumindest stellt sicher, dass Sie aufzuwickeln nicht mit nicht verwandten Getter aus Versehen bezeichnet.

0
Class c = Test.class; 
for(int i = 0; i < listOfAttributes.length; i++) 
{ 
    auxText += String.valueOf(c.getMethod("get" + listOfAttributes[i]).invoke(this, null)); 
} 

Sie können dies tun, etwas mehr elegant über Java Beans, die Introspector und PropertyDescriptor, aber es ist ein wenig langatmig:

Map<String, Method> methods = new HashMap<>(); 
Class c = this.getClass(); // surely? 
for (PropertyDescriptor pd : Introspector.getBeanInfo(c).getPropertyDescriptors()) 
{ 
    map.put(pd.getName(), pd.getReadMethod(); 
} 
// 
for (int i = 0; i < listOfAttributes.length; i++) 
{ 
    Method m = methods.get(listOfAttributes[i]); 
    if (m == null) 
     continue; 
    auxText += String.valueOf(m.invoke(this, null)); 
} 
Verwandte Themen