当前位置: 首页 > 知识库问答 >
问题:

java ObjectOutputStream方法的defaultWriteObject和writeObject之间的差异和相似性

吴安和
2023-03-14

我正在尝试了解java序列化机制,我几乎没有疑问

请回答以下有关java序列化的问题:

    < li >为什么使用< code > OOS . defaultwriteobject();?根据这篇文章,这是为了向后兼容。我不太明白它是怎么做到的。序列化的一个不兼容的变化是在新版本中删除一个字段。这意味着旧版本将不得不设置缺省值,这些值有时对用户无效。这与新版本添加新字段并允许设置缺省值有何不同? < li >在自定义序列化期间,同时使用< code>oos.defaultWriteObject()有什么不同吗;和< code>oos.writeObject(地址);这两者不是做同样的事情吗?我的意思是将所有超类和当前类的非瞬态非静态字段写入OOS。

这里

private void writeObject(java.io.ObjectOutputStream stream)
        throws IOException {
    stream.writeObject(name);
    stream.writeInt(id);
    stream.writeObject(DOB);
}

private void readObject(java.io.ObjectInputStream stream)
        throws IOException, ClassNotFoundException {
    name = (String) stream.readObject();
    id = stream.readInt();
    DOB = (String) stream.readObject();
}

上面的代码产生与下面的代码相同的结果

private void writeObject(java.io.ObjectOutputStream stream)
            throws IOException {
        stream.defaultWriteObject();
    }

    private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
         stream.defaultReadObject();
    }

什么时候使用这2个方法,什么时候使用只写对象(员工);//员工是我的整个对象//

  1. 这是一个可能的重复问题列表,无法回答我的问题。
  2. 问题1它说*如果在写入可选数据(如果有)之前没有调用defaultWriteObject或writeFields一次,那么在ObjectInputStream*的情况下实例反序列化的行为是未定义的,但是我仍然可以调用writeObject而不使用dearultwriteobject.right
  3. 问题2这些答案表示defaultwriteobject方法将一些额外的数据写入流,并反射性地检查要写入的内容。oos.writeobject(objectobj)不是也会进行反射检查吗
  4. 最后,我可以通过重写writeObject和ReadObject方法来控制序列化,那么Externalizable的作用是什么
  5. 如果提供串行版本UID不会引发异常,那么如果我反序列化了一个对象,而该对象的字段来自具有该字段的旧类,那么会发生什么?如果我提供自己的SerialverUID,基本上所有不兼容的更改会发生什么呢?它是否有自己的串行版本UID不会为所有兼容的更改抛出streamcorrupted异常

共有1个答案

伊铭
2023-03-14
  1. html" target="_blank">对象不是为了向后兼容。readObject是。
  2. 它们是相同的。defaultWriteObject是帮助您快速编写“可序列化”值。

考虑您的 Bean 添加了一个新字段。

class Bean implements Serializable {
  int id;
  String name;
  String newValue = "123";
}

尽管您已经为 newValue 提供了默认值,但 java 序列化将忽略它。(因为它分配实例而不是实例)

现在,如果不使用< code>readObject,将会得到< code>newValue=null。因此,您还需要在< code>readObject上进行初始化。

  private void readObject(ObjectInputStream stream) throws Exception {
    stream.defaultReadObject();
    this.newValue = "123";
  }

考虑您的bean几乎是“可序列化的”,除了某些字段。

请参见下面的代码。< code>BadThing不可< code >序列化,或者它包含一些您不想序列化的敏感数据。

class Bean implements Serializable {
  int id;
  String string;
  BadThing badThing;
}

要快速序列化它,可以让字段<code>transient</code>并编写<code>writeObject</code>方法来处理它

  private void writeObject(ObjectOutputStream stream) throws Exception {
    stream.defaultWriteObject();
    stream.writeInt(badThing.id);
  }

  // Corresponding `readObject`

当然你可以把defaultWriteObject替换成几个WriteXXX。但是如果你有很多很多字段,写代码又累又无聊,对吧?

所以defaultWriteObject只是为了让您免于编写无聊的代码。

 类似资料:
  • 问题内容: 很快就有两个相等运算符:double equals( )和Triple equals( ),两者之间有什么区别? 问题答案: 简而言之: 操作员检查其实例值是否相等, 操作员检查引用是否指向同一实例, 长答案: 类是引用类型,可能有多个常量和变量在幕后引用类的同一单个实例。类引用保留在运行时堆栈(RTS)中,其实例保留在内存的堆区域中。当您控制平等时, 这意味着它们的实例是否彼此相等。

  • 我编写了一个简单的脚本,它接受任意数量的参数来演示< code>$@和< code>$*之间的区别: 在我做的 CLI 上 这就是打印出来的 因为它们是相同的,这是否意味着等于?还是我遗漏了一点?

  • 问题内容: 已经尝试了一个示例程序来理解Java 6 和方法之间的区别。但是它们似乎是相同的,有什么建议吗? 问题答案: 区别在于,由于队列容量限制,添加失败时会发生什么: 引发(未经检查的)异常, 返回。 在实现的中记录了这一点。 值得注意的是,它没有容量限制,因此基本上不会抛出异常(并且总是会返回);例如,这与具有初始容量的建筑物不同。

  • 本文向大家介绍成本差异和进度差异之间的差异,包括了成本差异和进度差异之间的差异的使用技巧和注意事项,需要的朋友参考一下 对于任何应用程序或专门用于任何项目,最关注的因素之一是在开发前和开发后阶段的预算管理和时间管理。因此,要评估任何项目的这两个主要因素,有很多方法,其中成本差异和进度差异是两个重要且主要的方法。 顾名思义,“成本差异”基于项目开发中花费的成本,而“进度差异”则基于相同开发中花费的时

  • 问题内容: package main 该代码可以很好地工作。但是,如果按如下所示更改方法,则会导致死循环。区别在于将替换为。为什么? 问题答案: 因为程序包检查要打印的值是否具有方法(或换句话说:是否实现接口),如果是,则将调用它以获取值的表示形式。 软件包doc中对此进行了说明: […]如果操作数实现String()字符串方法,则将调用该方法将对象转换为字符串,然后根据动词的要求对其进行格式化(

  • 我正在通过做微控制器项目来自学C++。我当前的项目是使用一对或Adafruit羽毛分组无线电。无线电数据包的库函数需要一个C样式的字符串(我相信),我理解它是一个char的数组。 我已经设置了一个枚举来反映接收方的各种操作,并希望将该状态发送回发送方。所以我想把枚举变成char的数组。 在搜索将枚举转换为char数组的方法时,最简单的方法(对我来说)是将枚举变量传递给带有switch语句的函数,该