Java 序列化和不可变对象

Java 序列化和不可变对象,java,serialization,final,Java,Serialization,Final,我有一个用于不可变用途的类,因此我想标记所有字段final 但是,该类被序列化和反序列化以通过网络发送。要使其工作,需要一个空构造函数。这将阻止我创建最终字段 我相信这是一个相当普遍的问题,但我找不到解决办法。如何继续?不需要无参数构造函数。派生最多的不可序列化类确实需要一个可用于派生最少的可序列化类的无参数构造函数 如果您需要在readObject中变异字段,然后通过readResolve和writeReplace使用串行代理,在典型的序列化情况下,不要求类具有空构造函数或非最终字段才能序列化

我有一个用于不可变用途的类,因此我想标记所有字段
final

但是,该类被序列化和反序列化以通过网络发送。要使其工作,需要一个空构造函数。这将阻止我创建最终字段


我相信这是一个相当普遍的问题,但我找不到解决办法。如何继续?

不需要无参数构造函数。派生最多的不可序列化类确实需要一个可用于派生最少的可序列化类的无参数构造函数


如果您需要在
readObject
中变异字段,然后通过
readResolve
writeReplace

使用串行代理,在典型的序列化情况下,不要求类具有空构造函数或非最终字段才能序列化

现在,如果您必须进行自己的序列化,或者需要对一个未实现Serializable的类进行子类化,则情况就不同了


因此,您需要提供更多有关您是如何遇到问题的详细信息。

此问题是一个问题。(请注意,这仅适用于必须手动执行序列化的情况,例如使用readObject)

为了回应前面所说的内容,如果您采用的是实现
java.io.Serializable
接口,则不需要任何arg构造函数。看看
java.lang.Integer
源代码,例如,一个简单的可序列化/不可变类,它有两个构造函数:一个接受int,另一个接受字符串。源代码:。Javadoc:


还取决于类的复杂性和你正在做的事情,你可以考虑通过<代码> java .IO。ExtalabyI//Cuff>接口实现序列化(尽管有些人认为它过时了,但它确实需要一个无ARG构造函数)。这里是关于SO:的概述,这里是官方Java教程:。

请注意,因为我有一个类似的问题:
我收到一条消息“java.io.InvalidClassException:com.example.stuff.FooBar;com.example.stuff.FooBar;无有效构造函数”

我认为这是因为它缺少默认构造函数。但是上面的回答证实了它不是强制性的(但是我们的应用程序使用了一个旧的序列化程序,它确实需要一个默认的构造函数,所以这种情况可能会发生)

然后我找到一页,上面写着:

如果为继承而设计的类不可序列化,则 可能无法编写可序列化的子类。具体来说 如果超类不提供可访问的 无参数构造函数

我想这就是我得到的信息。核心问题似乎是经典的:我声明一个类是可序列化的,但超类不是!我在层次结构中向上移动了可序列化接口,一切都很好


但是这个信息有点误导…:-)

不需要无参数构造函数。让我们阅读源代码:

// java.io.ObjectStreamClass
private static Constructor<?> getSerializableConstructor(Class<?> cl) {
    Class<?> initCl = cl;
    while (Serializable.class.isAssignableFrom(initCl)) {
        if ((initCl = initCl.getSuperclass()) == null) {
            return null;
        }
    }
    ...
}
但是class
Son
不能:

class Father{
  private final int a;

  public Father(int a) {
    this.a = a;
  }
}

class Son extends Father implements Serializable {
  public Son(int a) {
    super(a);
  }
}

从评估中可以看出:“该问题适用于类的可序列化字段以外的最终实例字段”,因此在标准情况下,它可以正常工作。Nick似乎在做一些不同的事情。啊,是的,我应该添加一条免责声明,这只适用于必须挂接到readObject或类似的东西的情况。谢谢,我使用的是典型的序列化方法,但总是提供一个空构造函数,因为我认为它是这样工作的。
class Father{
  private final int a;

  public Father(int a) {
    this.a = a;
  }
}

class Son extends Father implements Serializable {
  public Son(int a) {
    super(a);
  }
}