简体   繁体   English

从Java对象动态选择字段

[英]Dynamically Selecting Fields from Java Objects

I've got an Object in Java representing the contents of a database, like so: 我有一个用Java表示数据库内容的对象,如下所示:

public Database {
    int varA;
    String varB;
    double varC;
}

Now I'm trying to select and order certain elements for forther processing, but I want to make it configurable, so I created an enum which represents all attributes of the object like 现在,我试图选择某些元素并对其进行排序,但我想使其可配置,因此我创建了一个枚举,表示该对象的所有属性,例如

public enum Contents {
    VarA,
    VarB,
    VarC;
}

So now when I create a selection like 所以现在当我创建一个选择像

Contents[] select = { Contents.VarC, Contents.VarB };

i want to generate a List of String values representing the actual database contents from this. 我想从此生成代表实际数据库内容的字符串值列表。 Now the only Implementation i could think of is switching for each entry in the selection, with has a pretty ugly quadratic complexity... 现在我能想到的唯一实现是切换选择中的每个条目,具有非常丑陋的二次复杂度...

public List<String> switchIT(Database db, Contents[] select) {
    List<String> results = new ArrayList<String>();

    for (Contents s : select) {
        switch(s) {
            case VarA:
                results.add(db.varA.toString());
                break;
            //go on...
        }
    }

    return results;
}

is there a more direct way to map between enum and dynamic object values? 有没有更直接的方式在枚举和动态对象值之间进行映射? Or in more general terms: What is the best way to select values from an object dynamically? 或更笼统地说:从对象动态选择值的最佳方法是什么?

Use the power of Java enums, which are fully-fledged classes. 使用Java枚举的强大功能,它们是成熟的类。

public enum Contents {
  VarA { public String get(Database d) { return d.getVarA(); } },
  VarB { public String get(Database d) { return d.getVarB(); } },
  VarC { public String get(Database d) { return d.getVarC(); } };
  public String get(Database d) { return ""; }
}

Your client code then becomes 然后,您的客户代码变为

public List<String> switchIT(Database db, Contents[] select) {
  List<String> results = new ArrayList<String>();
  for (Contents s : select) results.add(s.get(db));
  return results;
}

A more concise, but slower, solution would be to use a single implementation of get based on reflection and use the name of the enum member to generate the appropriate getter name: 一个更简洁但较慢的解决方案是使用基于反射的get的单个实现,并使用enum成员的名称来生成适当的getter名称:

public enum Contents {      
  VarA, VarB, VarC;

  private final Method getter;

  private Contents() {
    try {
      this.getter = Database.class.getMethod("get"+name());
    } catch (Exception e) { throw new RuntimeException(e); }
  }
  public String get(Database d) {
    try {
      return (String) getter.invoke(d); 
    } catch (Exception e) { throw new RuntimeException(e); }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM