Java创建具有深空对象的实例



我有一个嵌套了自定义对象类型的类。创建实例时,我希望使用默认值以及嵌套对象创建实例。我正在检查ApacheBeanUtils中是否有可用的实用程序类,但还没有。有什么简单的方法可以做到这一点吗?如果没有,我必须编写一个递归函数来实现这一点。例如

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)

在不改变实际类的结构的情况下,我想创建一个深度创建了空对象的实例。非常感谢您的任何想法!

这将满足您的需要,但需要注意一些事项:

  • 它假定有一个默认构造函数
  • 它跳过基元
  • 它跳过已初始化的对象
  • 它只会初始化指定的包(startsWith-match),以避免初始化其他东西,如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

相关内容

  • 没有找到相关文章