开发者

Java序列化与反序列化

开发者 https://www.devze.com 2023-04-03 10:37 出处:网络 作者: Sentiment.
目录Java 序列化与反序列化序列化APIObjectOutputStreamObjectInputStreamserialVersionUIDTransient (瞬态变量)实例理解readObject()方法重写实例理解总结Java 序列化与反序列化
目录
  • Java 序列化与反序列化
  • 序列化API
    • ObjectOutputStream
    • ObjectInputStream
    • serialVersionUID
  • Transient (瞬态变量)
    • 实例理解
  • readObject()方法重写
    • 实例理解
  • 总结

    Java 序列化与反序列化

    Java序列化把一个对象Java Object变为一个二进制字节序列byte[]

    Java反序列化就是把一个二进制字节序列byte[] 变为Java对象Java Object

    序列化API

    ObjectOutputStream

    字节输出流对象,将对象的输出流写到文件中(结合FileOutputStream使用)

    实例:

    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
    或
    FileOutputStream fout = new FileOutputStream("1.txt");
    ObjectOutputStream out = new ObjectOutputStream(fout);
    

    此外ObjectOutputStream还提供了writeObject()方法来序列化一个对象,并将它发送到输出流。

    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
    out.writeObject(new Test("Sentiment",10));        //对Test类中的构造方法进行传参
    

    ObjectInputStream

    字节输入流对象,将文件中的二进制字节序列进行反序列化操作(结合FileInputStream)

    实例:

    ObjectInputStream in = new ObjectInputStream(new FileInputStream("1.txt"));
    或
    FileInputStream fin = new FileInputStream("1.txt");
    ObjectInputStream oin = new ObjectInputStream(fin);
    

    此外ObjectInputStream还提供readObject()方法从流中取出下一个对象,并将对象反序列化。它的返回值为Object,因此,需要将它转换成合适的数据类型。

    ObjectInputStream In = new ObjectInputStream(new FileInputStream("1.txt"));
    Test o = (Test)In.readObject();
    System.out.println(o);        //读取后输出实例理解

    实例理解

    Test.java(类想要进行序列化操作,必须实现Serializable接口继承)

    package Sentiment.unjsserialize.demo01;
    
    import java.io.Serializable;
    
    public class Test implements Serializable {
        private String name;
        private int age;
    
        public Test() {
        }
    
        public Test(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Test{" + "name='" + name + '\'' + ", age=" + age + '}';
        }
    
    }
    

    Serializable.java

    package Sentiment.unserialize.demo01;
    
    import java.io.*;
    
    public class Serializable {
        public static void main(String[] args) throws IOException {
            ObjectOutputStreaphpm out = new ObjectOutputStream(new FileOutputStream("1.txt"));
            out.writeObject(new Test("Sentiment",10));
            out.close();
        }
    }
    

     UnSerializable.java

    package Sentiment.unserialize.demo01;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    
    public class UnSerializable {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            ObjectInputStream In = new ObjectInputStream(new FileInputStream("1.txt"));
            Test o = (Test)In.readObject();
            System.out.println(o);
        }
    }
    

    运行Serializable.java后便得到二进制字节码文件内容

    Java序列化与反序列化

    此时在运行UnSerializable.java便得到了二进制字节码反序列化后的内容

    Java序列化与反序列化

    serialVersionUID

    • 每个可序列化的类在序列化时都会关联一个版本号 , 这个版本号就是 serialVersionUID 属性
    • serialVersionUID 属性必须通过 static final long 修饰符来修饰 。
    • 如果可序列化的类未声明 serialVersionUID 属性 , 则 Java 序列化时会根据类的各种信息来计算默认的 serialVersionUID 值 . 但是 oracle 官方文档强烈建议所有可序列化的类都显示声明 serialVersionUID 值 .

    实例理解

    在Test.java中定义serialVersionUID 其值为1

    package Sentiment.unserialize.demo01;
    
    import java.io.Serializable;
    
    public class开发者_C学习 Test implements Serializable {
        public static finajsl long serialVersionUID = 1L;   //定义serialVersionUID 
    
        private  String name;
        private  int age;
    
        public Test() {
        }
    
        public Test(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        publicpython String toString() {
            return "Test{" + "name='" + name + '\'' + ", age=" + age + '}';
        }
    
    }
    

    此时运行Serializable.java进行序列化操作

    运行完毕后将serialVersionUID的值定义为2—>public static final long serialVersionUID = 2L;,在运行UnSerializable.java会报错

    Java序列化与反序列化

    Transient (瞬态变量)

    Transient( 瞬态变量 )是一个 Java 关键词 , 它用于标记类的成员变量在持久化到字节流时不要被序列化 ; 在通过网络套接字流传输字节流时 , transient 关键词标记的成员变量不会被序列化 。此为被static修饰的静态变量也不参与序列化操作。

    实例理解

    将Test.java中的nameage变量前分别加上transientstatic

    package Sentiment.unserialize.demo01;
    
    import java.io.Serializable;
    
    public class Test implements Serializable {
        public static final long serialVersionUID = 1L;  //定义serialVersionUID 
        private transient String name;                     //加上transient
        private static int age;                             //加上static
    
        public Test() {
        }
    
        public Test(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Test{" + "name=http://www.devze.com'" + name + '\'' + ", age=" + age + '}';
        }
    
    }
    

    此时在执行Serializable.java和UnSerializable.java,输出结果:Sentiment—>null,10—>0

    Java序列化与反序列化

    readObject()方法重写

    ​ 官方允许用户在被序列化的类中重写 readObject() 方法 , 重写后的方法将负责在反序列化时重构当前类对象 . 用户只需要在重写的 readObject() 方法中实现 defaultReadObject() 方法 , 就可以确保反序列化过程正常执行 .

    实例理解

    实现 defaultReadObject() 方法调用,并在Test类中重写该方法,在进行序列化和反序列化操作即可执行命令

    private void readObject(java.io.ObjectInputStream a) throws IOException, ClassNotFoundException{
        a.defaultReadObject();
        Runtime.getRuntime().exec("calc.exe");
    }
    

    Java序列化与反序列化

    总结

    • 类想要进行序列化操作,必须实现Serializable接口继承
    • 强烈建议定义serialVersionUID ,序列化、反序列化前后不要修改其值
    • 被static、Transient修饰的属性,不会进行序列化操作
    • readObject()方法重写时,需要实现defaultReadObject() 方法

     以上就是Java序列化与反序列化的详细内容,更多关于Java序列化与反序列化的资料请关注我们其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号