将数组项目动态映射到java.reflect.Field对象
问题描述:
我需要编写代码来模拟在运行时在类中提供用户定义数量的字段。这个想法是能够将指向这些“动态”字段的java.reflect.Field对象返回给客户端代码。将数组项目动态映射到java.reflect.Field对象
class DynamicFieldClass {
/**
* fieldNames is the list of names of the fields we want to "exist" in the class
* they will all be of the same type (say String)
*/
public DynamicFieldClass(List<String> fieldNames) {
// ... what do we do here
}
public Field getFieldObjectFor(String desiredFieldName) {
// ... what do we do here
}
}
是否有类似DynamicProxy(但字段)? 感谢
答
最后我用了Javassist到: - 在运行时,从我的原班 继承创建一个新的类定义 - 注入,我需要为新的类定义的字段
我也换成了公共构造通过一个静态工厂方法来创建和返回新类定义的一个实例。总而言之,代码如下所示:
class DynamicFieldClass {
protected DynamicFieldClass() {
}
public Field getFieldObjectFor(String desiredFieldName) {
return null;
}
/**
* fieldNames is the list of names of the fields we want to "exist" in the class
* they will all be of the same type (say String)
*/
public static createInstance (List<String> fieldNames) {
ClassPool defaultClassPool = ClassPool.getDefault();
CtClass originalClass = defaultClassPool.get("DynamicFieldClass");
CtClass newClass = defaultClassPool.makeClass("modified_DynamicFieldClass", originalClass);
StringBuilder getterCore = new StringBuilder();
for (String item : fieldNames) {
CtField addedField = CtField.make(String.format("private String %s;", item), newClass);
newClass.addField(addedField);
getterCore.append(String.format("if \"%s\".equals(%1) { return this.class.getDeclaredField(%s);}", item, item));
}
getterCore.append("throw new IllegalArgumentException(\"Unknown field name: \" + $1);");
final String sourceGeneralGetter = String.format("{%s}", getterCore.toString());
CtMethod mold = originalClass.getDeclaredMethod("getFieldObjectFor");
CtMethod copiedMeth = CtNewMethod.copy(mold, newClass, null);
newClass.addMethod(copiedMeth);
CtMethod getMeth = newClass.getDeclaredMethod("getFieldObjectFor");
getMeth.setBody(sourceGeneralGetter);
CtConstructor defaultCtor = new CtConstructor(new CtClass[0], newClass);
defaultCtor.setBody("{}");
newClass.addConstructor(defaultCtor);
Class modifiedClass = newClass.toClass();
return modifiedClass.newInstance();
}
}