【java】序列化与反序列化:原生和json

序列化的目的

  • 跨平台存储
  • 网络传输

序列化的方式

jdk原生

序列化与反序列化

@Test  
public void test01() throws Exception {
    
      
    //序列化  
    FileOutputStream fileOutputStream = new FileOutputStream("D:\\IDEA_file\\Learn_8\\src\\file\\person.dat");  
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);  
    objectOutputStream.writeBoolean(true);//boolean -> Boolean;  
    Person person = new Person(10, "小明");  
    //序列化对象  
    objectOutputStream.writeObject(person);  
    //关闭外层流  
    objectOutputStream.close();  
  
}  
@Test  
public void test02() throws Exception {
    
      
    //反序列化  
    FileInputStream fileInputStream = new FileInputStream("D:\\IDEA_file\\Learn_8\\src\\file\\person.dat");  
    ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);  
    boolean b = objectInputStream.readBoolean();  
    System.out.println(b);  
    Object o = objectInputStream.readObject();  
    System.out.println(o);  
    //向下转型  
    Person p=(Person) o;  
    System.out.println(p.toString());  
    objectInputStream.close();  
  
}

要求

被序列化的类实现Serializable接口

例如:

public final class String  
    implements java.io.Serializable
public class Person implements Serializable

serialVersionUID

作用:
标记一个类的版本,如果我们不指定版本号,每当我们修改或添加一个类的字段或者方法,jdk就会自动根据属性和方法等参数生成一个id号

反序列化的时候的id号和序列化时候的id号不一致就会反序列化失败

java.io.InvalidClassException: file.Person; local class incompatible: stream classdesc serialVersionUID = 7330609361009257993, local class serialVersionUID = -3573391668384454971

因此我们一般都会自己指定版本号,该字段必须是静态的、最终的和类型:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

不能被继承

public class Person implements Serializable {
    
      
    private static final long serialVersionUID = 1L;
}
  • 当兼容升级的时候,不修改版本号
  • 当不兼容升级的时候,修改版本号

[!Note] tip

避免被序列化

static

static 变量因为不属于任何对象(Object),所以无论有没有 transient 关键字修饰,均不会被序列化。

transient

如果有些字段不想进行序列化,

对于不想进行序列化的变量,使用 transient 关键字修饰。

transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。

关于 transient 还有几点注意:

  • transient 只能修饰变量,不能修饰类和方法。
  • transient 修饰的变量,在反序列化后变量值将会被置成类型的默认值。例如,如果是修饰 int 类型,那么反序列后结果就是 0
public class Person implements Serializable {
    
      
    private static final long serialVersionUID = 1L;  
    Integer age;  
    String name;  
    static Integer total=10;  
    transient Integer tall=178;
}

json

fastjson

@Test  
public void test1(){
    
      
    User user = new User("张三",1);  
    System.out.println(user);  
    System.out.println("-----fastjson-----");  
    // 将Java对象转换为json字符串  
    String jsonString=JSON.toJSONString(user);  
    System.out.println(jsonString);  
    // 将json反序列化为Java对象  
    User user1 = JSON.parseObject(jsonString,User.class);  
    System.out.println(user1);  
}
package com.gdb.mvc.controller;  
  
import java.io.Serializable;  
  
/**  
 * @Author gao  
 * @Description TODO  
 * @Date 2023/6/11 15:52  
 * @Version 1.0  
 */public class User  {
    
      
    String name;  
    Integer age;  
  
    @Override  
    public String toString() {
    
      
        return "User{" +  
                "name='" + name + '\'' +  
                ", age=" + age +  
                '}';  
    }  
  
    public User(String name, Integer age) {
    
      
        this.name = name;  
        this.age = age;  
    }  
  
    public String getName() {
    
      
        return name;  
    }  
  
    public void setName(String name) {
    
      
        this.name = name;  
    }  
  
    public Integer getAge() {
    
      
        return age;  
    }  
  
    public void setAge(Integer age) {
    
      
        this.age = age;  
    }  
}

jackson

gson

猜你喜欢

转载自blog.csdn.net/weixin_50799082/article/details/131157245