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不关心私有字段,但反序列化过程本身关心私有字段?