Java案例如何反序列化对象?

wen java案例 11

本文目录导读:

Java案例如何反序列化对象?

  1. 基本反序列化示例
  2. 多种反序列化方式
  3. 安全性考虑 - 验证反序列化
  4. 完整示例 - 序列化和反序列化
  5. 注意事项
  6. 常见问题解决

在Java中,反序列化对象是将之前通过序列化保存的字节流重新恢复为Java对象的过程,以下是完整的案例说明:

基本反序列化示例

首先创建一个可序列化的类

import java.io.Serializable;
public class Person implements Serializable {
    // 序列化版本号,建议显式声明
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private String email;
    // transient关键字修饰的字段不会被序列化
    private transient String password;
    public Person(String name, int age, String email, String password) {
        this.name = name;
        this.age = age;
        this.email = email;
        this.password = password;
    }
    // getter和setter方法
    public String getName() { return name; }
    public int getAge() { return age; }
    public String getEmail() { return email; }
    public String getPassword() { return password; }
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + 
               ", email='" + email + "', password='" + password + "'}";
    }
}

反序列化方法

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
public class DeserializationExample {
    public static void main(String[] args) {
        String filename = "person.ser";
        // 从文件反序列化对象
        Person person = deserializeFromFile(filename);
        if (person != null) {
            System.out.println("反序列化成功!");
            System.out.println(person);
            // password是transient,所以会为null
            System.out.println("Password (transient): " + person.getPassword());
        }
    }
    /**
     * 从文件反序列化对象
     */
    public static Person deserializeFromFile(String filename) {
        Person person = null;
        try (FileInputStream fileIn = new FileInputStream(filename);
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            // 读取对象
            person = (Person) in.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            System.err.println("反序列化失败: " + e.getMessage());
        }
        return person;
    }
}

多种反序列化方式

import java.io.*;
import java.util.Base64;
public class MultipleDeserializationMethods {
    /**
     * 从文件反序列化
     */
    public static Object fromFile(String filePath) throws Exception {
        try (FileInputStream fis = new FileInputStream(filePath);
             ObjectInputStream ois = new ObjectInputStream(fis)) {
            return ois.readObject();
        }
    }
    /**
     * 从字节数组反序列化
     */
    public static Object fromByteArray(byte[] data) throws Exception {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(bais)) {
            return ois.readObject();
        }
    }
    /**
     * 从Base64字符串反序列化
     */
    public static Object fromBase64String(String base64Str) throws Exception {
        byte[] data = Base64.getDecoder().decode(base64Str);
        return fromByteArray(data);
    }
    /**
     * 从输入流反序列化
     */
    public static Object fromInputStream(InputStream inputStream) throws Exception {
        try (ObjectInputStream ois = new ObjectInputStream(inputStream)) {
            return ois.readObject();
        }
    }
    // 使用示例
    public static void main(String[] args) {
        try {
            // 1. 从文件
            Person person1 = (Person) fromFile("person.ser");
            // 2. 从字节数组
            byte[] data = /* 获取字节数组 */;
            Person person2 = (Person) fromByteArray(data);
            // 3. 从Base64字符串
            String base64Str = /* 获取Base64字符串 */;
            Person person3 = (Person) fromBase64String(base64Str);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

安全性考虑 - 验证反序列化

import java.io.*;
import java.util.Arrays;
import java.util.List;
public class SafeDeserialization {
    // 白名单 - 允许反序列化的类
    private static final List<String> WHITE_LIST = Arrays.asList(
        "Person",
        "java.lang.String",
        "java.util.ArrayList"
    );
    /**
     * 安全的反序列化(使用白名单)
     */
    public static Object safeDeserialize(byte[] data) throws Exception {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
             SafeObjectInputStream sois = new SafeObjectInputStream(bais)) {
            return sois.readObject();
        }
    }
    /**
     * 自定义ObjectInputStream,实现白名单验证
     */
    static class SafeObjectInputStream extends ObjectInputStream {
        public SafeObjectInputStream(InputStream in) throws IOException {
            super(in);
        }
        @Override
        protected Class<?> resolveClass(ObjectStreamClass desc) 
                throws IOException, ClassNotFoundException {
            String className = desc.getName();
            // 检查是否在白名单中
            if (!isWhitelisted(className)) {
                throw new SecurityException("反序列化被拒绝: " + className);
            }
            return super.resolveClass(desc);
        }
        private boolean isWhitelisted(String className) {
            for (String allowed : WHITE_LIST) {
                if (className.contains(allowed)) {
                    return true;
                }
            }
            return false;
        }
    }
}

完整示例 - 序列化和反序列化

import java.io.*;
public class CompleteExample {
    public static void main(String[] args) {
        // 1. 创建原始对象
        Person originalPerson = new Person("张三", 25, "zhangsan@example.com", "123456");
        System.out.println("原始对象: " + originalPerson);
        // 2. 序列化到文件
        try (FileOutputStream fos = new FileOutputStream("person.ser");
             ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            oos.writeObject(originalPerson);
            System.out.println("序列化成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 3. 从文件反序列化
        try (FileInputStream fis = new FileInputStream("person.ser");
             ObjectInputStream ois = new ObjectInputStream(fis)) {
            Person deserializedPerson = (Person) ois.readObject();
            System.out.println("反序列化后的对象: " + deserializedPerson);
            // 验证反序列化结果
            System.out.println("\n验证结果:");
            System.out.println("Name: " + deserializedPerson.getName());
            System.out.println("Age: " + deserializedPerson.getAge());
            System.out.println("Email: " + deserializedPerson.getEmail());
            // transient字段为null
            System.out.println("Password (应为null): " + deserializedPerson.getPassword());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

注意事项

  1. 版本控制:始终声明 serialVersionUID
  2. 安全性:反序列化可能存在安全风险,建议使用白名单验证
  3. 异常处理:处理好 IOException 和 ClassNotFoundException
  4. transient关键字:标记的字段不会被序列化/反序列化
  5. 资源管理:使用 try-with-resources 自动关闭流

常见问题解决

// 当serialVersionUID不匹配时的处理
public class CompatiblePerson implements Serializable {
    // 使用默认值,允许向后兼容
    private static final long serialVersionUID = 1L;
    // 添加新字段时的处理
    private String newField;
    // 自定义反序列化逻辑
    private void readObject(ObjectInputStream in) 
            throws IOException, ClassNotFoundException {
        // 执行默认反序列化
        in.defaultReadObject();
        // 执行自定义逻辑
        if (newField == null) {
            newField = "默认值";
        }
    }
}

这就是Java反序列化的完整案例,涵盖了基本用法、多种方式、安全性考虑和最佳实践。

抱歉,评论功能暂时关闭!