序列化和不可变对象

csga3l58  于 2021-07-05  发布在  Java
关注(0)|答案(6)|浏览(325)

我有一个用于不可变用途的类,因此我想标记所有字段 final .
但是,该类被序列化和反序列化以通过网络发送。要使其工作,需要一个空构造函数。这会阻止我创建最终字段。
我确信这是一个相当普遍的问题,但我找不到解决办法。我该怎么办?

nimxete2

nimxete21#

在典型的序列化情况下,不要求类具有空构造函数或非final字段才能序列化。
现在,如果您必须进行自己的序列化,或者需要对一个没有实现serializable的类进行子类化,那就不同了。
所以你需要提供一些你是如何遇到问题的更多细节。

9bfwbjaz

9bfwbjaz2#

这个问题是java语言上的一个公开错误(请注意,这仅适用于必须手动执行序列化的情况,例如使用readobject)

ie3xauqp

ie3xauqp3#

不需要no arg构造函数。派生最多的不可序列化类不需要可用于派生最少的可序列化类的无参数构造函数。
如果你需要在 readObject ,然后通过 readResolve 以及 writeReplace .

sd2nnvve

sd2nnvve4#

为了回应前面所说的,如果您选择实现 java.io.Serializable 接口。看一看这个 java.lang.Integer 例如,一个简单的可序列化/不可变类,它有两个构造函数:一个接受int,另一个接受字符串。源代码:http://www.docjar.com/html/api/java/lang/integer.java.html. javadoc公司:http://java.sun.com/javase/6/docs/api/java/lang/integer.html.
还可以考虑通过 java.io.Externalizable 接口(尽管有些人认为它过时了,而且它确实需要no-arg构造函数)。下面是关于so的概述:java中可序列化和可外部化的区别是什么?下面是正式的java教程:http://java.sun.com/docs/books/tutorial/javabeans/persistence/index.html.

1u4esq0p

1u4esq0p5#

作为记录,因为我有一个类似的问题:
我收到一条消息“java.io.invalidclassexception:com.example.stuff.foobar;com.example.stuff.foobar;“没有有效的构造函数”
我认为这是因为它缺少一个默认的构造函数。但是上面的答案证实它不是强制性的(但是我们的应用程序。使用确实需要默认构造函数的旧序列化程序,因此可能会出现这种情况)。
然后我发现一页写着:
如果为继承而设计的类不可序列化,则可能无法编写可序列化的子类。具体地说,如果超类不提供可访问的无参数构造函数,这将是不可能的。
我想这就是我得到的信息。核心问题似乎是经典的:我声明一个类是可序列化的,但超类不是!我在层次结构中向上移动了可序列化接口,一切都很好。
但这个信息有点误导……:-)

nzrxty8p

nzrxty8p6#

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

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

因此,实际上在最近的not中需要no arg构造函数 Serializable 在类型层次结构中初始化。
意思是下一节课 Domain 可以序列化。

class Domain implements Serializable {
    private final int a;

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

但是班级 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);
  }
}

相关问题