【问题标题】:Java execution logic while using custom Serialization使用自定义序列化时的 Java 执行逻辑
【发布时间】:2013-06-17 20:20:08
【问题描述】:

我在实现特殊序列化(序列化甚至是瞬态对象)时一直试图弄清楚流程,但我无法理解流程:

public class object1 implements Serializable {

int i = 2032423;
String str = "dssadsadsdfsfsdfczxc";
StringBuilder sb = new StringBuilder();
transient testobject ob1 = new testobject();
String str2;
testobject ob2;
String sooo =new String("jbdskdbshxcbc");

public static void main(String[] args) throws ClassNotFoundException {


    try {

        FileOutputStream fos = new FileOutputStream(new File(
                "serialTst.txt"));
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        object1 obj1 = new object1();
        obj1.ob1.str = "this guy is referred";
        oos.writeObject(obj1);
        oos.flush();
        oos.close();
        fos.close();

        FileInputStream fis = new FileInputStream("serialTst.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        object1 obb=(object1)ois.readObject();
        System.out.println(obb.str2);

        ois.close();
        fis.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

private void readObject(ObjectInputStream Aois)
        throws ClassNotFoundException, IOException {
    Aois.defaultReadObject();
    str2 = (String) Aois.readObject();  

    System.out.println(ob1.str);
    System.out.println(sooo);    // Why Null here??
}

private void writeObject(ObjectOutputStream Aoos) throws IOException {

    Aoos.defaultWriteObject();
    Aoos.writeObject(ob1.str);
}

}

** 为什么 String sooo 为 null,即使打印正常 (String sooo="something") ????**

如果没有创建object1类的实例,那么readObject和writeObject是怎么执行的??

【问题讨论】:

  • @luigi 感谢您的关注,但您的解决方案肯定会起作用,但我想知道为什么,我建议的方法不起作用???
  • 您应该在我的回答中发布此评论,而不是在您的问题中。另外,我的名字是双 G :)。

标签: java serialization execution


【解决方案1】:

ob1 未被序列化,因为它被标记为transient。此外,在反序列化对象时,Java 不会执行,也不会执行类的构造函数,也不会为字段设置默认值,而是会使用 Java 默认值填充 transient 字段,即 int 使用 0、@987654325 @ 与 null,因此您的 ob1 字段值为 null

修复 readObject 方法中的代码,您应该在使用之前初始化 ob1 字段:

private void readObject(ObjectInputStream Aois)
    throws ClassNotFoundException, IOException {
    Aois.defaultReadObject();
    str2 = (String) Aois.readObject();  //this is totally ok
    ob1 = new testobject();
    ob1.str = (String) Aois.readObject(); //this should work
    System.out.println(ob1.str);
}

【讨论】:

  • @SachinVerma 可能我没有很好地解释这一点。简单来说,反序列化对象时,transient 对象引用字段将具有 null 值(这是反序列化时的默认行为)。因此,当在你的readObject 方法中使用ob1 时,它将是null,所以你需要在使用它之前创建它。
  • 嘿,但是 String sooo 也是空的??
  • @SachinVerma 它不应该。你能发布完整的代码来进行评估吗?
  • 嘿,你解决了为什么 ob1 没有被初始化的困惑。(感谢这个)但是 STring sooo 仍然返回 null。 (请参阅更新的问题)
  • @SachinVerma 这很奇怪,不应该发生。可能你没有执行你看到的代码。
【解决方案2】:

所以我想问的是为什么会有 NullPointerException,为什么是 ob1 没有初始化?

反序列化既不调用给定Serializable 实现类的constructor 也不调用instance initializer。这意味着,当通过反序列化从字节流中创建对象时,声明为transient 并因此未序列化的类的成员变量将初始化为default value。你的情况

transient testobject ob1 = new testobject();

deserialization 期间不会执行。但是,由于正在创建对象,因此通过JLS12.5 必须将字段初始化为默认值。在反序列化时,可序列化类object1 的所有字段(未标记为瞬态和静态)都从流中恢复,transient 变量(ob1)初始化为默认值null .这就是为什么下面一行:

System.out.println(ob1.str);

由于ob1.str,在您的readResolve 方法中抛出NullPointerException

那么这些方法(readObject、writeObject)是如何开始它们的 执行

readObjectwriteObject方法被JVM自动调用,分别写入和读取对象。

为什么 String sooo 即使在正常情况下也是 null (String sooo="something") 会被打印出来????

不,String sooo 不能为空,除非您在序列化之前将其设为 null

【讨论】:

  • no String soo=new STring("whatevr") 未打印。你可以自己检查一下
  • @SachinVerma: soo 不为空。我认为你得到的NullPointerException 是因为ob1.str。而且您将其误解为soo。或者,也许这不是您正在运行的程序。
猜你喜欢
  • 2014-01-26
  • 1970-01-01
  • 2011-02-04
  • 2021-11-09
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
相关资源
最近更新 更多