我需要在方法中创建和填充对象。唯一的信息是成员字段名称(作为字符串传递)以及该字段的相关值(作为Object传递)。考虑到性能,最合适的设计模式是什么? - 反思,如果有罚款,则不是首选方法。
更新
要设置的值来自一个对象,该对象充当值的生成器,该对象具有一组返回特定字段的适当值的方法。例如。对于会员Double x;
,它将是generator.getX()
答案 0 :(得分:1)
将所有getter复制到所有可用setter的简单函数如下。通过一些更多的工作,您可以缓存此信息并加快速度,但它可能足够快。
public static <T> T copyTo(Object from, T to) {
for(Method m : to.getClass().getMethods()) {
if (!m.getName().startsWith("set") || m.getParameterCount() != 1)
continue;
try {
Method getter = from.getClass().getMethod("g" + m.getName().substring(1));
m.invoke(to, getter.invoke(from));
} catch (NoSuchMethodException ignored) {
// ignored
} catch (InvocationTargetException | IllegalAccessException e) {
throw new AssertionError(e);
}
}
return to;
}
注意:只有匹配的getter和setter的字段才会尝试从一个字段复制到另一个字段。
public static void main(String[] args) {
One orig = new One(1, "hi", 3);
One to = new One();
One copy = copyTo(orig, to);
System.out.println(to);
}
static class One {
int x;
String y;
double z;
public One() {
}
public One(int x, String y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
public double getZ() {
return z;
}
public void setZ(double z) {
this.z = z;
}
@Override
public String toString() {
return "One{" +
"x=" + x +
", y='" + y + '\'' +
", z=" + z +
'}';
}
}
打印
One{x=1, y='hi', z=3.0}
如果要通常创建对象,则需要使用反射。
唯一的选择是字节码生成,实现起来要复杂得多,只能节省一小部分微秒。
为了节省微秒,需要多少天才能实现此目的?
答案 1 :(得分:1)
如果您知道对象的类名,那么您可以做的是:
public Object populate(String className,String fieldName,Object value) throws Exception{
Class clazz = Class.forName(className);
Object o = null;
for(Field f: clazz.getFields()){
if(f.getName().equals(fieldName)){
o = clazz.getConstructor().newInstance();//default constructor if it exists
f.set(o, value);
break;
}
}
return o;
}
编辑: 既然你知道了这个类(有问题的评论)那么你可以使用的是我用这个改变写的函数,而不是className参数:
Class clazz = Class.forName(YourClass.class.getName());
EDIT2: 如果我理解更新,您询问如何知道调用哪个方法来获取值。 在您的生成器类中,您可以获取它具有的方法列表。然后,如果您的方法名为getFieldName(),则可以在具有字段名称后找到名为getFiledName的方法。 例如:
for(Method m:GeneratorClass.class.getMethods()){
System.out.println(m.getName());
//analyze method name and field name to determine which method to call
//..
boolean callThis = true;//result of analysis
if(callThis){
//Object value = m.invoke(obj);
//obj==generator
}
}