序列化Java中属于继承层次结构的对象?

序列化Java中属于继承层次结构的对象?,java,Java,我在继承层次结构中有一些类,它们的状态需要序列化。比如: public class Base { private int b; public void serialize(Writer w) { w.write(b); } } public class DerivedA extends Base { private int a; public void serialize(Writer w) { super.serialize

我在继承层次结构中有一些类,它们的状态需要序列化。比如:

public class Base {
    private int b;

    public void serialize(Writer w) {
        w.write(b);
    }
}

public class DerivedA extends Base {
   private int a;

   public void serialize(Writer w) {
      super.serialize(w);
      w.write(a, some_option);
}

public class DerivedC extends Base {
   private int c;

   public void serialize(Writer w) {
       super.serialize(w);
       w.write(c, some_other_option);
   }
}
将它扩展到几十个类和每个类几十个成员,这有点维护问题。我希望通过将成员更改为属性对象,然后使用反射或其他方法来查找要序列化的字段,从而对该逻辑进行编码


不过,我想不出一个好方法来获取类的所有继承字段,尤其是在继承链比玩具示例更深的情况下。做这件事的最佳方法是什么?

在不确切知道类代表什么的情况下,这听起来像是一项组合作业,而不是继承作业。将它们包装到其他类中


您可以在一个类中尝试
int b
,在另一个类中尝试
int a
,依此类推,并创建另一个类来保存字段中的这些内容,通过注释处理生成不可变和可序列化类的库正是为这类事情而创建的。

首先,称这种“静态行为”有点误导。这意味着您正在谈论
静态方法。但您不是,而且(从技术上讲)Java
静态方法和字段无论如何都不是继承/可继承的

你问题的核心是:

我想不出一个好方法来获取类的所有继承字段(使用反射),尤其是在继承链比玩具示例更深的情况下。最好的方法是什么

方法是访问超类的目标类链中的所有类,调用
Class::getDeclaredFields()
获取该类声明的所有字段。(这不包括继承的字段…因此需要遍历该链。)对于返回的每个字段,您需要根据类型和修饰符确定在序列化程序中要执行的操作。对于私有字段,需要使用
field::setAccessible
。这非常昂贵,因此典型的序列化程序实现会捕获它所需的信息并对其进行缓存

这似乎不是一个“好”的方法,但这是唯一的方法。。。假设您正在实现自己的序列化框架。另一种方法是使用预先存在的序列化框架;e、 对象流,JAXB,Jackson,GSON,等等。或者基于JPA或JDP的数据持久化机制。

使用Java的旧版(自JDK 1.1开始提供)
Serializable
ObjectOutputStream
功能,这些功能在内部依赖于反射,但您不必担心:

public class Base implements Serializable {
    private int b;

    public void serialize(Writer w) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);            
        w.write(new String(baos.toByteArray());
    }
}

public class DerivedA extends Base {
   private int a;    
}

public class DerivedC extends Base {
   private int c;
}

尽管这仍然有效,但它已经过时了,现在我通常建议使用Jackson将其序列化为JSON格式,而不是从
ObjectOutputStream

中产生的二进制格式。通常,当您觉得反射是答案时(尤其是这里需要的非平凡反射),它指出了一个需要在代码中改进的设计问题。几乎可以肯定的是,这里的情况是这样的——但如果不了解您试图实现的目标的更广泛背景,就很难准确地说您应该如何改变它。您是对的,我的问题的关键是如何序列化这种状态,而不必到处重复我自己。我认为普通的旧java序列化在这里对我不起作用,因为有些字段是对其他复杂对象的引用,我可能想对其进行序列化,例如,只是序列化一个ID。在推荐一个框架时,是否应该问另一个问题,或者这是离题的?这是离题的。正如我在对Stephen C的回答的评论中提到的,与可序列化的帐户相比,事情需要如何序列化有更多的细微差别。谢谢你的回答。