Java 序列化/反序列化机制
比如说,我有一个类Java 序列化/反序列化机制,java,serialization,deserialization,Java,Serialization,Deserialization,比如说,我有一个类X,它有一个字段值,即 类X实现了可序列化{ 私有int值; // ... } 此外,这里没有显示getter和setter。这个类是序列化的。 在反序列化结束时,同一个类具有值字段,并且访问说明符是公共的。此外,这个类没有getter和setter。因此,我的问题是: 如果字段的访问说明符发生更改,或者类中的某些或所有方法在反序列化结束时丢失,反序列化是否会失败 反序列化过程中字段赋值的机制是什么 我真的不知道你是如何得到这个结果的,但是你告诉我的是而不是序列化的默认行为。
X
,它有一个字段值,即
类X实现了可序列化{
私有int值;
// ...
}
此外,这里没有显示getter和setter。这个类是序列化的。
在反序列化结束时,同一个类具有值字段,并且访问说明符是公共的。此外,这个类没有getter和setter。因此,我的问题是:
我真的不知道你是如何得到这个结果的,但是你告诉我的是而不是序列化的默认行为。所以,我猜你用错了。以下是一些示例代码:
public class X implements Serializable
{
private int value;
public int getValue() { return value; }
}
这里是序列化/反序列化过程:
X x = new X();
x.setValue(4);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputSteam(buffer);
oos.writeObject(x);
oos.flush();
oos.close();
ByteArrayInputStream in = new ByteArrayInputStream(buffer.toByteArray());
ObjectInputStream ois = new ObjectInputStream(in);
Object obj = ois.readObject();
if (obj instanceof X)
{
X readObject = (X) obj;
System.out.println(readObject.getValue());
}
你可能曾经得到过你的结果。确保使用和而不是方法名称中未声明
的变量。使用java序列化进行序列化/反序列化不需要getter/setter,例如,检查以下代码:
public class Main {
public static class Q implements Serializable {
private int x;
public Q() {
x = 10;
}
public void printValue() {
System.out.println(x);
}
}
public static void main(String[] args) throws Exception {
Q q = new Q();
FileOutputStream fos = new FileOutputStream("c:\\temp.out");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(q);
fos.close();
FileInputStream fis = new FileInputStream("c:\\temp.out");
ObjectInputStream oin = new ObjectInputStream(fis);
Q q2 = (Q)oin.readObject();
fis.close();
q2.printValue();
}
}
一些好的链接
1) 如果字段的访问说明符无效,反序列化是否失败
更改或部分或全部方法在
反序列化结束
序列化使用反射进行
Java使用
private static final long serialVersionUID
默认值涉及哈希代码。序列化根据以下信息创建一个长类型的哈希代码:
- 类名和修饰符
- 类实现的任何接口的名称
- 除私有方法和构造函数外的所有方法和构造函数的说明
- 除private、static和private transient之外的所有字段的说明
序列化机制的默认行为是一种经典的“比抱歉更安全”策略。序列化机制使用suid(默认为极其敏感的索引)来告诉类何时发生了更改。如果是这样,序列化机制将拒绝使用与旧类序列化的数据创建新类的实例
2) 字段赋值的机制是什么
在反序列化过程中
真正的细节可以读入
回答您的问题:
序列化有一个基本的健全性检查,以查看序列化结束是否使用相同版本的类:serialVersionUID
成员必须相等。阅读本节了解更多信息。基本上,它是一个静态值,您可以通过在类中声明它来管理自己,也可以让编译器为您生成一个静态值。如果编译器生成它,对类的任何更改都将导致serialVersionUID
的更改,因此,如果端点没有完全相同的类,反序列化将失败。如果要避免这种情况,请自己声明变量,并在更改类的成员变量确实会导致类不兼容时手动更新它
Java虚拟机在这里发挥了巨大的作用,它可以直接访问所有内部状态,而不需要getter(标记为transient
或static
的字段不会序列化)。另外,虽然Serializable
接口没有指定任何要实现的方法,但是有许多“神奇的方法”,您可以声明它们来影响序列化过程。请阅读“”部分及以后的内容以了解更多信息。但是请注意,您应该谨慎使用这些工具,因为它们可能会混淆任何维护开发人员
如果字段的访问说明符发生更改,反序列化是否会失败
没有
或者在反序列化端的类中缺少某些或所有方法
是,除非接收类具有值等于流中编码的值的serialVersionUID
成员
反序列化过程中字段赋值的机制是什么
太宽了,但是:
- 反思,以及
- 名称匹配(而不是按类和流中的位置匹配)
此链接提供序列化的工作原理@DeadProgrammer:链接已断开。您不知道他是如何得到什么结果的?问题中没有提到任何结果。所以serialVersionUID不关心私有字段,但反序列化过程本身关心私有字段?