Java序列化与反序列化

Mathieu 于 2025-07-28 发布

序列化与反序列化

概念

序列化:Java对象——>字节序列

反序列化:字节序列——>Java对象

代码演示

先写一个类User

import java.io.Serializable;

public class User implements Serializable {
    private String name;
    private int age;

    public User() {
        System.out.println("调用无参构造函数");
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("调用有参构造函数");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

序列化user对象成ser.bin文件

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class Ser {
    public static void main(String[] args) throws Exception {
        User user = new User("xc",18);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(user);
    }
}

反序列化ser.binuser

import java.io.*;

public class Ser {
    public static void main(String[] args) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));
        Object o = ois.readObject();
        System.out.println(o);
    }
}

写成方法

import java.io.*;

public class Ser {
    public static void serializable (String path, Object obj) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
        oos.writeObject(obj);
    }
    public static Object unserializable (String path) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
        return ois.readObject();
    }
    public static void main(String[] args) throws Exception {
        User user = new User();
        serializable("ser.bin",user);
        System.out.println(unserializable("ser.bin"));
    }
}

安全方面问题

简单说就是如果User这个类里面实现了ObjectInputStream 里面的readObject() 方法那就会执行这个方法,比如exec

代码如下:

User.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class User implements Serializable {
    private String name;
    private int age;
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        Runtime.getRuntime().exec("calc");//正常是没这一行的,在研究安全方面时可以理解为这里就是顺便执行的“私货”
    }
    public User() {
        System.out.println("调用无参构造函数");
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("调用有参构造函数");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Ser.java

import java.io.*;

public class Ser {
    public static void serializable (String path, Object obj) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
        oos.writeObject(obj);
    }
    public static Object unserializable (String path) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
        return ois.readObject();
    }
    public static void main(String[] args) throws Exception {
        User user = new User();
        serializable("ser.bin",user);
        System.out.println(unserializable("ser.bin"));
    }
}

即可弹出计算器