2016-07-11 3 views
1

Ich habe mehrere Klassen, die Wrapper-Methoden erfordern, die wie folgt aussehen:Aufruf Java-Methode Karte unter Verwendung von Werten

class MyClass { 
    public MyClass(String arg1, Date arg2, Integer arg3) { 
    // Do something with supplied arguments 
    } 
} 

class MyClassWrapper { 
    private ArrayList<MyClass> objects = new ArrayList<MyClass>(); 
    private final String[] names = {"firstparam","secondparam","thirdparam"}; 
    private final Object[] classes = {String.class,Date.class,Integer.class}; 

    public void addEntry(Map<String, Object> params) { 
    objects.add(new MyClass(
       (String)params.get(names[0]), 
       (Date)params.get(names[1]), 
       (Integer)params.get(names[2]) 
       )); 
    } 

    public ArrayList<MyClass> getEntries() { 
    return objects; 
    } 

    public Object[] getColumnClasses() { 
    return classes; 
    } 

    public String[] getColumnLabels() { 
    return names; 
    } 
} 

Diese im Code verwendet werden, die Daten aus externen Quellen in ein HashMap liest und ruft dann addEntry anrufen der MyClass Konstruktor. Ich schreibe meine eigenen ***Wrapper Klassen, so dass ich keinen zusätzlichen MyClass Konstruktor hinzufügen muss, um die Map direkt zu lesen.

Alle sehen meine ***Wrapper Klassen die gleiche, außer für verschiedene names und classes Mitglieder und eine handgeschriebene addEntry hat. Gibt es eine Möglichkeit zu vermeiden, addEntry manuell zu schreiben, names und classes zu verwenden, um die Kartenwerte automatisch in den MyClass-Konstruktor zu übergeben?

+0

Ja, Sie könnten wahrscheinlich etwas zusammen mit Reflexion zusammenbasteln. –

+0

@EliottFrisch Es fühlt sich an wie etwas, das zur Kompilierzeit getan werden könnte (mit Generika?). Wenn dies C++ wäre, würde ich eine clevere Metaprogrammierungslösung erwarten ... – beldaz

+1

Beachten Sie, dass es nur sehr einfach ist, mit Java 8 auf Parameternamen zuzugreifen (um sie in der Map nachzuschlagen). Mit früheren Versionen von Java möchten Sie wahrscheinlich eine Bibliothek, Spring und andere haben Unterstützung dafür (durch Lesen und Parsing der .class-Datei) –

Antwort

0

Hier ist eine Lösung für Sie:

Schritt 1:

Es folgt MyClass.java genau wie in der Frage angegeben.

public class MyClass { 

private String arg1; 
private Date arg2; 
private Integer arg3; 

public MyClass(String arg1, Date arg2, Integer arg3) { 
     this.arg1 = arg1; 
     this.arg2 = arg2; 
     this.arg3 = arg3; 
    } 

@Override 
public String toString() { 
     return "MyClass [arg1=" + arg1 + ", arg2=" + arg2 + ", arg3=" + arg3 + "]"; 
    } 

} 

Schritt 2:

erstellen Sie nun die Wrapper-Klasse MyClassWrapper.java wie folgt:

import java.lang.reflect.Constructor; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Map; 

public class MyClassWrapper<T> { 
    private List<T> objects = new ArrayList<T>(); 
    private String[] names; 
    private Class<?>[] classes; 
    private Class<T> clazz; 

    public MyClassWrapper(Class<T> clazz, String[] names, Class<?>[] classes) throws Exception { 
     this.clazz = clazz; 
     this.names = names; 
     this.classes = classes; 
    } 

    public void addEntry(Map<String, Object> params) throws Exception { 
     Constructor<T> constructor = clazz.getConstructor(classes); 
     Object[] parameters = new Object[names.length]; 
     for (int i = 0; i < names.length; i++) { 
      parameters[i] = params.get(names[i]); 
     } 
     objects.add(constructor.newInstance(parameters)); 
    } 

    public List<T> getEntries() { 
     return objects; 
    } 

    public Class<?>[] getColumnClasses() { 
     return classes; 
    } 

    public String[] getColumnLabels() { 
     return names; 
    } 
} 

Schritt 3:

nun folgende Klasse MyClassWrapperDemo wird MyClassWrapper testen mit Parameter MyClass. Aber Sie können MyClassWrapper mit anderen Klassen verwenden, die ähnlich aussehen wie MyClass. Sie müssen keine andere Version der Wrapperklasse definieren.

import java.util.Arrays; 
import java.util.Date; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

public class MyClassWrapperDemo { 
    public static void main(String[] args) throws Exception { 
     MyClassWrapper<MyClass> wrapper= 
       new MyClassWrapper<MyClass>(
       MyClass.class, 
       new String[]{"firstparam", "secondparam", "thirdparam" }, 
       new Class<?>[]{String.class, Date.class, Integer.class} 
       );  
     Map<String, Object> params =new HashMap<String, Object>(); 
     params.put("firstparam", "HelloWorld"); 
     params.put("secondparam", new Date()); 
     params.put("thirdparam", 30); 
     wrapper.addEntry(params); 
     List<MyClass> list= wrapper.getEntries(); 
     String[] lebels = wrapper.getColumnLabels(); 
     Class<?>[] objects= wrapper.getColumnClasses(); 
     System.out.println(list); 
     System.out.println(Arrays.toString(lebels)); 
     System.out.println(Arrays.toString(objects)); 

    } 

} 
+0

Dies ist auch eine gute Lösung. Auch hier sieht es so aus, als ob jemand es abgelehnt hat, ohne zu erklären warum, was für mich wie schlechte Manieren aussieht. +1 von mir obwohl. – beldaz

+0

Hallo @beldaz kannst du bitte nochmal meine Antwort sehen?Die Klasse 'MyClassWrapper' ist nun wirklich parameterbasiert, da ihr verschiedene Namen und Klassenmitglieder zugewiesen werden können. –

+0

Danke, ja, sieht genau so aus, wie ich es brauche. Es ist nicht viel drin zwischen deinem und Matts, aber ich akzeptiere deins, da es früher gepostet wurde. Es wäre nützlich gewesen zu wissen, warum jemand das Bedürfnis hatte, es abzustimmen, aber aus meiner Sicht sieht es großartig aus. – beldaz

0

Scheint mir, dass Sie ein Factory-Muster wollen. Mit Reflektion können Sie es tun. Brauchen nur eine Schnittstelle und Implementierungsklassen mit jeweils eigenen Verhaltensweisen. Diese Klasse, die Sie bauen, könnte die Fabrik sein.

+1

Das hört sich nach einer Möglichkeit an, aber ich hatte auf etwas konkreteres gehofft. Können Sie den Beispielcode erweitern? – beldaz

Verwandte Themen