gpt4 book ai didi

java - readObjectNoData 何时被调用

转载 作者:行者123 更新时间:2023-11-30 02:22:12 26 4
gpt4 key购买 nike

我正在阅读Effective Java Item74。我对java对象的序列化很感兴趣。但一种方法“readObjectNoData”让我感到困惑。

这里是JavaDoc的解释

For serializable objects, the readObjectNoData method allows a class to control the initialization of its own fields in the event that a subclass instance is deserialized and the serialization stream does not list the class in question as a superclass of the deserialized object. This may occur in cases where the receiving party uses a different version of the deserialized instance's class than the sending party, and the receiver's version extends classes that are not extended by the sender's version. This may also occur if the serialization stream has been tampered; hence, readObjectNoData is useful for initializing deserialized objects properly despite a "hostile" or incomplete source stream.

它说当我序列化一个对象时,它是旧版本,不会扩展父类,但是当我反序列化时,该类升级到新版本并扩展其他一些类。

我真的很想玩这个。所以我有一个 Employee 类

public class Employee implements Serializable { //v1
public String name;
public int age;
protected String address;
static final long serialVersionUID = 1L;

public Employee()
{
name= "John";
age = 1;
address ="N/A";
}

public Employee(String name , int age, String address)
{
this.name = name;
this.age = age;
this.address = address;
}
}

还有一个序列化类

public class Se {
public static void main(String [] args) {
Employee e = new Employee();

try {
FileOutputStream fileOut =
new FileOutputStream("tmp.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in tmp.txt");
}catch(IOException i) {
i.printStackTrace();
}
}
}

将 Employee 对象序列化到 tmp.txt 后,我​​更改了 Employee 类

public class Employee extends Person { //v2
protected String address ;
static final long serialVersionUID = 1L;
public Employee()
{
super();
address ="N/A";
}

public Employee(String name , int age, String address)
{
super(name,age);
this.address = address;
}
private void readObjectNoData() throws ObjectStreamException {
name = "John";
age = 1;
}
}

这是我的 Person 类

class Person implements Serializable{
protected String name;
protected int age;

Person() {
this("John",1);
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
}

当我通过反序列化类进行反序列化时

public class De {
public static void main(String [] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("tmp.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i) {
i.printStackTrace();
System.out.println("IOException");
return;
}catch(ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}

System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("Age: " + e.age);
}
}

输出始终显示

Deserialized Employee...
Name: null
Address: N/A
Age: 0

即使我在 readObjectNoData 方法中设置调试点,它也永远不会被触发,我在网上找不到任何可运行的示例,所以我在这里提供了很多代码。有谁知道我错过了什么?

如有任何意见,我们将不胜感激。

最佳答案

这是一种独特的情况,其中类的反序列化器具有基于子类(Person)的类(Employee)版本。

子类可以说“如果我的基类不在序列化数据中也没关系 - 只需创建一个空基类即可。

Edit below

尝试这两个版本的“反序列化”。我的意思是序列化您的 v1 员工,然后尝试以下操作:

import java.io.Serializable;
public class Employee extends Person implements Serializable { //v2
protected String address ;
static final long serialVersionUID = 1L;

public Employee()
{
super();
address ="N/A";
}

public Employee(String name , int age, String address)
{
super(name,age);
this.address = address;
}

}

Person

import java.io.ObjectStreamException;
import java.io.Serializable;

class Person implements Serializable{
protected String name;
protected int age;

Person() {

}

Person(String name, int age) {
this.name = name;
this.age = age;
}
private void readObjectNoData() throws ObjectStreamException {

name = "cccc";
age = 1;
throw new IllegalArgumentException();
}
}

您将看到一个异常

Exception in thread "main" java.lang.IllegalArgumentException
at test.serialization.Person.readObjectNoData(Person.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeReadObjectNoData(ObjectStreamClass.java:1089)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1955)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at test.serialization.De.main(De.java:22)

希望有帮助

关于java - readObjectNoData 何时被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46481605/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com