【问题标题】:Java OOP transient field initialising upon loading POJO parent加载 POJO 父项时初始化 Java OOP 瞬态字段
【发布时间】:2019-03-04 01:55:12
【问题描述】:

所以我有一个非常大的类,其中包含数百个瞬态对象,每次加载父级(在本例中为 Person.class)时都需要重新初始化。 (Peron.class 被加载并保存)

以下是我目前的班级结构的示例:

public final class Person {

    private transient ObjectA a;
    private transient ObjectB b;
    private transient ObjectC c;
    private transient ObjectD d;
    //and hundreds more...

    public Person() {

        initTransientObjects();

    }

    private void initTransientObjects() {

        a = new ObjectA();
        b = new ObjectB();
        c = new ObjectC();
        d = new ObjectD();
        //and hundreds more...
    } 

    public void onReloadAfterFirstSave() {
        initTransientObjects();
    }

}

这使得编写新对象变得非常乏味,我想知道是否有一种方法可以像这样更紧凑:

public final class Person {

    private transient ObjectA a = new ObjectA();
    private transient ObjectB b = new ObjectB();
    private transient ObjectC c = new ObjectC();
    private transient ObjectD d = new ObjectD();
    //and hundreds more...
    //this way I only have to type the new object once instead of twice

    public void onReloadAfterFirstSave() {
        //what here? because now transient fields are null
    }

}

请注意,我不能使用上面的原因是,显然当 Person 再次加载时,瞬态字段将不会被加载,因此会自动设置为 null。

我应该在这里做什么?

编辑:

我还保存在 Person 类中的非瞬态对象以及这些瞬态字段,这就是为什么不能使用它的原因:

Peron person = new Person(); //every load

【问题讨论】:

  • 这看起来很奇怪......你是在将对象写入磁盘吗?为什么要在 Person 类中引用这么多不同的类型?
  • 它被保存为一个对象,但把它想象成一个真实的人,他会有很多属性,比如电视、汽车、房子等......
  • 如果你序列化这个人而不是它的数据——它仍然没有任何意义。你需要一种不同的抽象。在不知道你在构建什么的情况下,你的代码很难重构。
  • 更不用说你所有的对象在每次“reloadafterfirstsave”之后都会失去它的状态,此时它与仅仅执行“person = new Person()”没有什么不同(除非你有非瞬态属性你没有提到的)
  • 我确实序列化了一些 Person 的数据(这不是暂时的;这里没有显示,因为这不是问题所在),但是这个人会有一些需要每次重置的东西加载,例如,car 和 house 不会是瞬态的并且会被保存,但是,像 TodaysTVProgramSchedule.class 这样的对象会改变(假设玩家每天都重新加载)

标签: java class oop syntax initialization


【解决方案1】:

你可以试试这个,但我不赞成这样做,主要是因为你需要非常小心例外情况。 我会假设您的 ObjectA、ObjectB、ObjectC 的构造函数不是空的,如果是,那么这将更容易实现。

我为你做了一个示例类

import java.lang.reflect.InvocationTargetException;
import java.util.Random;

/**
 *
 * @author emngaiden
 */
public class Test2 {

    ClassContainer[] containers;
    Object[] instantieted_objects;

    public Test2() {
        initObjects();
    }

    public static void main(String[] args) {
        Test2 test=new Test2();
        StringBuilder sb=(StringBuilder)test.getObject(2);
        sb.append((String)test.getObject(0));
        sb.append(((Random)test.getObject(1)).nextDouble());
        System.out.println(sb.toString());
    }

    public Object getObject(int i){
        return this.instantieted_objects[i];
    }

    private void initObjects() {
        //total number of objects ObjectA, ObjectB etc...
        int number_of_objects = 3;
        this.containers = new ClassContainer[number_of_objects];
        this.instantieted_objects = new Object[number_of_objects];
        //create the containers, you write this only one, and can
        //share it between objects of the same class
        this.containers[0] = new ClassContainer(String.class,
                new Class[]{String.class},
                new Object[]{"hello world"}
        );
        this.containers[1] = new ClassContainer(Random.class,
                new Class[]{long.class},
                new Object[]{192323l}
        );
        this.containers[2] = new ClassContainer(StringBuilder.class,
                null,
                null
        );
        //poblate the objects in the array
        for(int i=0; i<this.containers.length; i++){
            try{
                this.instantieted_objects[i]=instantiateObject(containers[i]);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

    //returns a new object instance based on the container
    private Object instantiateObject(ClassContainer container)
    throws NoSuchMethodException, InstantiationException, IllegalAccessException,
    IllegalArgumentException, InvocationTargetException {
        //no arguments for the constructor means that the constructor is empty
        if(container.args!=null){
            //get the constructor that matches the Class[] array on its arguments
            return 
                container.obj.getConstructor(container.args)
                .newInstance(container.values);
        }
        else{
            return container.obj.newInstance();
        }
    }

    //class to hold the necessary data to instantiate the object
    public class ClassContainer {

        //the target class, for ObjectA(int,int)this must be ObjectA.class 
        Class obj;
        //the argument classes, it would be {int.class,int.class}
        Class[] args;
        //the actual values for the constructor, it would be {1,2}
        Object[] values;

        public ClassContainer(Class obj, Class[] args, Object[] values) {
            this.obj = obj;
            this.args = args;
            this.values = values;
        }
    }
}

编写代码很有趣,但我不建议使用它。

【讨论】:

  • 有趣。我之前在其他项目上做过这个,发现创建带有额外转换所需的 getter 和 setter(这不能用 ide 自动完成)与我正在使用的仅 oop 类型方法一样乏味。但我也想听听其他人对此的看法
猜你喜欢
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
相关资源
最近更新 更多