# Java 序列化与 Jackson 序列化机制对比

1. Java 序列化机制

1.1 定义

Java 序列化是将对象的状态转换为字节序列的过程,以便可以将对象持久化到文件、通过网络传输或存储到缓存中。反序列化则是将字节序列恢复为对象的过程。

1.2 实现 Serializable 接口

  • Serializable 接口:是一个标记接口,没有方法。它用于指示 Java 序列化机制该类的对象可以被序列化。

  • 示例 :

    java 复制代码
    import java.io.Serializable;
    
    public class MyObject implements Serializable {
        private static final long serialVersionUID = 1L;
    
        private String name;
        private int age;
    
        // Getters and Setters
        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 "MyObject{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

1.3 序列化与反序列化操作

  • 序列化 :使用 ObjectOutputStream 将对象写入流。

    java 复制代码
    import java.io.FileOutputStream;
    import java.io.ObjectOutputStream;
    
    public class SerializationExample {
        public static void main(String[] args) {
            MyObject myObject = new MyObject();
            myObject.setName("Kimi");
            myObject.setAge(25);
    
            try (FileOutputStream fileOutputStream = new FileOutputStream("myObject.ser");
                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
                objectOutputStream.writeObject(myObject);
                System.out.println("Object serialized successfully.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
  • 反序列化 :使用 ObjectInputStream 从流中读取对象。

    java 复制代码
    import java.io.FileInputStream;
    import java.io.ObjectInputStream;
    
    public class DeserializationExample {
        public static void main(String[] args) {
            try (FileInputStream fileInputStream = new FileInputStream("myObject.ser");
                 ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
                MyObject myObject = (MyObject) objectInputStream.readObject();
                System.out.println("Deserialized Object: " + myObject.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

1.4 serialVersionUID 的作用

  • 唯一标识符 :serialVersionUID 是一个静态常量字段,用于标识类的版本。它在序列化和反序列化过程中用于验证类的版本是否一致。

  • 自动生成 :如果不显式定义 serialVersionUID,Java 会根据类的结构自动生成一个值。但建议显式定义一个固定的值,以避免因类结构变化导致的版本不一致问题。

  • 示例 :

    java 复制代码
    private static final long serialVersionUID = 1L;

1.5 类结构变化与 serialVersionUID

  • 字段添加/删除:

    • 如果类的结构变化不大(如添加或删除一些非关键字段),可以保持 serialVersionUID 不变。反序列化时,新字段的值会是其默认值。

    • 示例:添加字段 address,但保持 serialVersionUID 不变。

      java 复制代码
      private String address;
  • 字段类型改变:

    • 如果字段类型发生改变,需要更新 serialVersionUID 的值。否则,反序列化时会抛出 InvalidClassException。

    • 示例:将字段 age 从 int 改为 String,并更新 serialVersionUID。

      java 复制代码
      private static final long serialVersionUID = 2L;
      private String age;
  • 字段数量大幅变化:

    • 如果字段数量发生大幅变化(如删除多个字段),建议更新 serialVersionUID 的值,以避免反序列化时出现不一致的问题。

1.6 注意事项

  • 安全性:反序列化时可能会引入安全风险,建议仅从可信源加载序列化数据。
  • 性能:Java 的默认序列化机制相对低效,如果需要高性能,可以考虑使用更高效的序列化框架(如 Kryo、Protocol Buffers 等)。

2. Jackson 序列化机制

2.1 定义

Jackson 是一个流行的 JSON 处理库,用于将 Java 对象序列化为 JSON 格式的字符串,以及将 JSON 格式的字符串反序列化为 Java 对象。它广泛应用于 RESTful API 的开发中。

2.2 使用 Jackson 进行序列化和反序列化

  • 序列化:将 Java 对象转换为 JSON 格式的字符串。

    java 复制代码
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class JacksonSerializationExample {
        public static void main(String[] args) {
            MyObject myObject = new MyObject();
            myObject.setName("Kimi");
            myObject.setAge(25);
    
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonString = objectMapper.writeValueAsString(myObject);
                System.out.println("Serialized JSON: " + jsonString);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
  • 反序列化:将 JSON 格式的字符串转换为 Java 对象。

    java 复制代码
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class JacksonDeserializationExample {
        public static void main(String[] args) {
            String jsonString = "{\"name\":\"Kimi\",\"age\":25}";
    
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                MyObject myObject = objectMapper.readValue(jsonString, MyObject.class);
                System.out.println("Deserialized Object: " + myObject.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

2.3 Jackson 的特点

  • 基于 JSON:Jackson 使用 JSON 格式进行序列化和反序列化,适合 Web 应用和 RESTful API。
  • 注解支持 :通过注解(如 @JsonProperty、@JsonIgnore 等)可以控制序列化和反序列化的行为。
  • 性能优化:Jackson 提供了高效的序列化和反序列化性能,适合处理大量数据。

2.4 示例类

java 复制代码
import com.fasterxml.jackson.annotation.JsonProperty;

public class MyObject {
    @JsonProperty("name")
    private String name;

    @JsonProperty("age")
    private int age;

    // Getters and Setters
    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 "MyObject{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3. Jackson 与 Java 序列化机制的不同

3.1 序列化格式

  • Java 序列化:将对象序列化为二进制格式,适合持久化和网络传输。
  • Jackson 序列化:将对象序列化为 JSON 格式的字符串,适合 Web 应用和 RESTful API。

3.2 是否需要实现接口

  • Java 序列化 :需要实现 java.io.Serializable 接口。
  • Jackson 序列化:不需要实现任何接口,但可以通过注解来控制序列化和反序列化的行为。

3.3 性能

  • Java 序列化:相对低效,尤其是处理大量数据时。
  • Jackson 序列化:性能优化较好,适合处理大量数据。

3.4 安全性

  • Java 序列化:存在反序列化漏洞的风险,建议仅从可信源加载序列化数据。
  • Jackson 序列化:相对安全,但仍需注意 JSON 数据的来源。

3.5 使用场景

  • Java 序列化:适合需要将对象持久化为二进制文件或通过网络传输二进制数据的场景。
  • Jackson 序列化:适合需要将对象转换为 JSON 格式(如 RESTful API 的响应)或从 JSON 格式还原为对象的场景。

4. 总结

  • Java 序列化:

    • 需要实现 Serializable 接口。
    • 使用二进制格式,适合持久化和网络传输。
    • 需要显式定义 serialVersionUID,并在类结构发生变化时手动更新。
    • 相对低效,存在安全风险。
  • Jackson 序列化:

    • 不需要实现任何接口
相关推荐
Rain的Java大神之路39 分钟前
设计一套生产级 API 接口:从契约、安全、幂等到限流,我踩过的坑都在这了
java·后端·面试
SimonKing41 分钟前
零配置也能白嫖前沿大模型!dsh-our-free-model插件真香警告
java·后端·程序员
nice_lcj52042 分钟前
【从零理解 Spring AI · 15】让检索更准:先宽召回,再精排序
java·后端·rag·spring ai·ai应用开发·检索优化·重排序
回家路上绕了弯1 小时前
要人确认的那一步,在确认什么?
后端
IT_陈寒2 小时前
JavaScript项目实战经验分享:从内存泄漏到性能优化的血泪史
前端·人工智能·后端
杨凯凡2 小时前
Spring Boot 链路追踪实战:Micrometer、TraceId 与异步线程上下文传播
java·spring boot·后端
非优秀程序员11 小时前
第07章 孙德良的阳谋|《互联网产品恩仇录》
javascript·后端
非优秀程序员11 小时前
第06章 浙江帮的内战|《互联网产品恩仇录》
后端
非优秀程序员11 小时前
第08章 马云的反击|《互联网产品恩仇录》
后端
非优秀程序员11 小时前
题记|《互联网产品恩仇录》
后端·程序员·创业