动态地将数组项映射到 java.reflect.Field 对象

发布于 2024-10-27 03:47:19 字数 506 浏览 1 评论 0原文

我需要编写代码来模拟在运行时类中具有用户定义数量的可用字段。这个想法是能够将指向这些“动态”字段的 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 的东西(但是对于字段)? 谢谢

I need to write code that simulates having a user-defined number of fields available in a class at runtime. The idea being to be able to return java.reflect.Field objects pointing to those "dynamic" fields to client-code.

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
 }
}

Is there something similar to DynamicProxy (but for fields)?
Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情痴 2024-11-03 03:47:19

我最终使用 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();
}

}

I ended up using Javassist to :
- create a new class definition at runtime that inherits from my original class
- inject the fields I needed into the new class definition

I also replaced the public constructor by a static factory method that makes and returns an instance of the new class definition. All in all, the code looks like this:

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();
}

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文