使用反射设置财产的财产

时间:2016-12-16 11:27:40

标签: java reflection

假设我们有一个班级structure

class Street {
    String name;
    List<Building> buildings;
}

class Building {
    String number;
    int floors;
    List<Apartment> apartments;
}

class Apartment {
    String owner;
}

runtime我对上面的结构一无所知。我所拥有的只是一个object和一个String参数,其中包含有关我必须分配的属性的数据。

例如String "buildings.0/floors#5"意味着我必须将列表中第一个Building的floors属性分配给5.而String "buildings.0/apartments.1/owner#Luke"意味着我必须为“Luke”分配所有者属性第二栋公寓位于第一栋楼的公寓中。

我知道如何使用反射分配属性。但是,如果我们必须分配属性本身的属性呢?是否可以实现这样的逻辑?

2 个答案:

答案 0 :(得分:1)

我刚刚根据你的结构做了一个简单的解决方案。这有很多要添加(NullPointerException,OutOfBounds,...)但是为了正确输入,你有一个正确的答案。

然后你只需要方法,一个设置值,一个从列表中获取实例。两者都需要使用反射。

public Object getListItem(Object o, String name, int index) throws Exception{
    return ((List)o.getClass().getDeclaredField(name).get(o)).get(index);
}

public void setValue(Object o, String name, Object value) throws Exception{
    o.getClass().getDeclaredField(name).set(o, value);
}

就像说的那样,没有检查,我做的很简单,因为我是从头开始做的。

然后,只需要根据/解析String(再次,不检查)来找到每个[变量/值]块。并找到这是什么类型:

  • 如果它包含#,则为归属
  • 如果它包含.,则这是列表中的getter

所以这应该是这样的。

public void init(Object o, String pattern) throws Exception{
    String[] array = pattern.split("/");
    for(String s : array){
        if(s.contains("#")){
            String[] param = s.split("\\#");
            setValue(o, param[0], param[1]);
        } else {
            String[] list = s.split("\\.");
            o = getListItem(o, list[0], Integer.parseInt(list[1]));
        }
    }
}

以下是您可以在ideone here

上找到的示例的输出

那将输出

[Street] Foo [
        [Building] 1 1[[Apartment] null, [Apartment] null], 
        [Building] 2 2[[Apartment] null, [Apartment] null, [Apartment] null, [Apartment] null], 
        [Building] 3 1[[Apartment] null, [Apartment] null]]
[Street] Foo [
        [Building] 1 1[[Apartment] null, [Apartment] null], 
        [Building] 2 3[[Apartment] null, [Apartment] null, [Apartment] null, [Apartment] null], 
        [Building] 3 1[[Apartment] null, [Apartment] null]]
[Street] Foo [
        [Building] 1 1[[Apartment] null, [Apartment] null], 
        [Building] 2 3[[Apartment] null, [Apartment] null, [Apartment] null, [Apartment] null], 
        [Building] 3 1[[Apartment] null, [Apartment] John]]

答案 1 :(得分:1)

如果您的类遵循JavaBeans约定(标准getter和setter封装字段),则可以使用Introspector以及依赖它的几个框架。

我最喜欢的例子是Spring's BeanWrapper technology,它允许你编写如下代码:

BeanWrapper bw = new BeanWrapperImpl(street);
bw.setPropertyValue("buildings[0].appartments[1].owner", "luke");