Java使用深空对象创建实例

时间:2014-04-29 19:18:06

标签: java reflection recursion

我有一个嵌套了自定义对象类的类。当我创建一个实例时,我希望使用默认值和嵌套对象创建实例。我正在检查Apache Bean Utils中是否有可用的实用程序类,但还没有运气。有没有简单的方法来做到这一点?如果没有,我必须写一个递归函数来做到这一点。 E.g。

A{
 int x;
 B b;
 C c;    
}

B{
 boolean y;
 D d;     
}

D{
 String z;
}

Object a = A.class.newInstance();

上面应该给我一个像下面这样的对象,其中a,b,c,d填充了默认值(仅适用于基元)

 a 
  |--> x (=0)
  |
  |--> b
  |
  |--> c
       |--> y (=false)
       |
       |--> d
            |--> x (=null)

在不改变实际类的结构的情况下,我想创建一个深度创建空对象的实例。任何想法都高度赞赏!

1 个答案:

答案 0 :(得分:2)

这可以做你想要的一些警告:

  • 它假设有一个默认构造函数。
  • 它会跳过原语。
  • 它跳过已经初始化的对象。
  • 它只会初始化指定的包(startsWith匹配),以避免初始化其他像HashMaps等非常混乱的东西。
  • 它仅使用简单的对象进行测试。
  • 如果您设置了安全管理器策略,则可能无法访问这些字段。
  • 如果有任何类型的递归循环,例如obj_A有obj_B有一个obj_A那么它会因堆栈溢出而失败。
  • 它不会从超类访问和设置值(但可以使用)。

我会问这是否是最好的解决方案,因为如果事情在对象深处不尽如人意,那么它很容易失败。

Initializer.java

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;

import org.example.something.A;

public class Initilizer {

    public static void initialize(Object object, Set<String> packages)
            throws IllegalArgumentException,
            IllegalAccessException {
        Field[] fields = object.getClass().getDeclaredFields();

        for (Field field : fields) {
            String fieldName = field.getName();
            Class<?> fieldClass = field.getType();

            // skip primitives
            if (fieldClass.isPrimitive()) {
                System.out.println("Skipping primitive: " + fieldName);
                continue;
            }

            // skip if not in packages
            boolean inPackage = false;
            for (String pack : packages) {
                if (fieldClass.getPackage().getName().startsWith(pack)) {
                    inPackage = true;
                }
            }
            if (!inPackage) {
                System.out.println("Skipping package: "
                        + fieldClass.getPackage().getName());
                continue;
            }

            // allow access to private fields
            boolean isAccessible = field.isAccessible();
            field.setAccessible(true);

            Object fieldValue = field.get(object);
            if (fieldValue == null) {
                System.out.println("Initializing: " + fieldName);
                try {
                    field.set(object, fieldClass.newInstance());
                } catch (IllegalArgumentException | IllegalAccessException
                        | InstantiationException e) {
                    System.err.println("Could not initialize "
                            + fieldClass.getSimpleName());
                }
            } else {
                System.out
                        .println("Field is already initialized: " + fieldName);
            }

            fieldValue = field.get(object);

            // reset accessible
            field.setAccessible(isAccessible);

            // recursive call for sub-objects
            initialize(fieldValue, packages);
        }

    }

    public static void main(String[] args) throws Exception {

        A a = new A();

        // Packages to initialize
        Set<String> packages = new HashSet<>();
        packages.add("com.example");
        packages.add("org.example");

        initialize(a, packages);
    }
}

A.java

package org.example.something;

import com.example.other.B;

public class A {

    private int x;

    private B b;

    private B be = new B();

    private C c;

}

B.java

package com.example.other;

public class B {

    private boolean y;

    private D d;

}

C.java

package org.example.something;
import java.util.HashMap;

public class C {

    private HashMap doNotInit;

}

D.java

package com.example.other;

public class D {

    private String s;

}

输出

Skipping primitive: x
Initializing: b
Skipping primitive: y
Initializing: d
Skipping package: java.lang
Field is already initialized: be
Skipping primitive: y
Initializing: d
Skipping package: java.lang
Initializing: c
Skipping package: java.util