使用 Map 值调用 Java 方法
Call Java method using Map values
我有几个 类 需要类似于此的包装方法:
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;
}
}
这些用于从外部源读取数据到 HashMap
然后调用 addEntry
以调用 MyClass
构造函数的代码。我自己写 ***Wrapper
类 这样我就不需要添加额外的 MyClass
构造函数来直接读取 Map
。
我所有的 ***Wrapper
类 看起来都一样,只是有不同的 names
和 classes
成员,以及一个手写的 addEntry
。有没有办法避免手动编写 addEntry
以利用 names
和 classes
自动将映射值传递给 MyClass
构造函数?
在我看来,您想要工厂模式。使用反射你可以做到。只需要一个接口和实现 classes,每个都有自己的行为。您建造的这个 class 可能就是工厂。
这是适合您的一种解决方案:
第 1 步:
以下内容 MyClass.java
与问题中指定的完全一致。
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 + "]";
}
}
第 2 步:
现在创建包装器 class MyClassWrapper.java
如下:
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;
}
}
第 3 步:
现在跟随 class MyClassWrapperDemo
将用参数 MyClass
测试 MyClassWrapper
。但是您可以将 MyClassWrapper
与其他看起来类似于 MyClass
的 class 一起使用。您不需要定义另一个版本的包装器 class.
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));
}
}
我有几个 类 需要类似于此的包装方法:
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;
}
}
这些用于从外部源读取数据到 HashMap
然后调用 addEntry
以调用 MyClass
构造函数的代码。我自己写 ***Wrapper
类 这样我就不需要添加额外的 MyClass
构造函数来直接读取 Map
。
我所有的 ***Wrapper
类 看起来都一样,只是有不同的 names
和 classes
成员,以及一个手写的 addEntry
。有没有办法避免手动编写 addEntry
以利用 names
和 classes
自动将映射值传递给 MyClass
构造函数?
在我看来,您想要工厂模式。使用反射你可以做到。只需要一个接口和实现 classes,每个都有自己的行为。您建造的这个 class 可能就是工厂。
这是适合您的一种解决方案:
第 1 步:
以下内容 MyClass.java
与问题中指定的完全一致。
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 + "]";
}
}
第 2 步:
现在创建包装器 class MyClassWrapper.java
如下:
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;
}
}
第 3 步:
现在跟随 class MyClassWrapperDemo
将用参数 MyClass
测试 MyClassWrapper
。但是您可以将 MyClassWrapper
与其他看起来类似于 MyClass
的 class 一起使用。您不需要定义另一个版本的包装器 class.
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));
}
}