Java技术栈 —— 序列化与反序列化

Java技术栈 —— 序列化与反序列化

Serialization is the conversion of the state of an object into a byte stream; deserialization does the opposite.[2]
序列化: 将对象转换成字节流,以便将对象信息持久存储起来。三体人的脱水
反序列化: 将字节流转换为对象,以便将持久存储的对象信息加载为真正的对象。三体人的浸泡
那么脱水之后就方便携带、存储、传输,甚至是 —— 永生(这就是序列化的目的,将对象信息持久存储起来,毕竟大刘也没说脱水后的三体人会不会死),等到恒纪元来临时,就可以浸泡,将来的某一天,也会诞生对人的序列化与反序列化技术,即将思想和记忆上传至云端,然后等新的肉体成长好再下载到新的肉体里,这种技术对伦理的颠覆将是前所未有的。实际上这样去思考对象的序列化,你会发现一些共通之处。

序列化的一些规定

  • (1)属于这个类的static属性不会被序列化。就像人的眼睛数量就是人这个类的static属性,没变异的话,nums_of_eye=2是恒定的,没必要对固定不变的重复事情序列化。
  • (2)如果有成员变量为类,那么这个类也必须可以被序列化。
  • (3)transient关键字。用在序列化中,所以平常几乎没什么机会见到它,如果你不想某些属性被序列化,那就在这个属性前面加上transient[7],就比如,女人永远都是刚满十八岁,dddd,所以嘛,女生对于年龄这种敏感信息从来都不会写在纸上,你得用心体会。据说华为OD某员工说因为代码编程时,输出了用户个人信息,被领导一顿批,搞不好就是这种细节的地方没注意到,谁知道呢,知道的可以留个言。
// Person.java
import java.io.Serializable;

/**
 * @ClassName: Person
 * @Author: 键盘国治理专家
 * @email: [email protected]
 * @Time: 2024/1/10 下午2:46
 * @Description:该类涉及以下知识点
 * (1)类成员属性的默认作用域为default
 * (2)private static final long serialVersionUID = 1L;的作用?
      序列化前和反序列化后,这个UID都必须相同,
      要不然序列化的不是同一个对象,就会报错,如果不写的话,JVM会自动生成,但是这样就不保证可移植性了,因为这取决于编译器,所以高度建议手写
 * (3)transient关键字的作用?
      如果你不想某些属性被序列化,那就在这个属性前面加上transient
 *
 * @Version: 1.0
 */
public class Person implements Serializable {
    /*
    static的变量不会被序列化,那么这个ID会吗?
    前面说过了,static是不会的,那么这个ID显然也是不能例外的,
    那么JVM如何检查序列化前和序列化后的这个ID值是否一致呢?
    通过Hash函数,想了解更多,请看参考文章[1]。
    */
    private static final long serialVersionUID = 2L; 
    static String country = "ITALY"; //不会被序列化,作用域为默认的default
    private int age;
    private String name;
    transient int height; //transient??

    // getters and setters

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}
//TestDemo.java
import java.io.*;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * @ClassName: Main
 * @Author: 键盘国治理专家
 * @email: [email protected]
 * @Time: 2024/1/10 下午2:50
 * @Description:
 * @Version: 1.0
 */
public class TestDemo {
    @Test
    public void whenSerializingAndDeserializing_ThenObjectIsTheSame() throws IOException, ClassNotFoundException {
        Person person = new Person();
        person.setAge(20);
        person.setName("Joe");
        person.setHeight(199);

        // (1)Writing an object into a file.
        FileOutputStream fileOutputStream
                = new FileOutputStream("./yourfile.txt");
        ObjectOutputStream objectOutputStream
                = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(person);
        objectOutputStream.flush();
        objectOutputStream.close();

        // (2)Reading an object from a file.
        FileInputStream fileInputStream
                = new FileInputStream("./yourfile.txt");
        ObjectInputStream objectInputStream
                = new ObjectInputStream(fileInputStream);
        Person p2 = (Person) objectInputStream.readObject();
        objectInputStream.close();

        assertTrue(p2.getAge() == person.getAge());
        assertTrue(p2.getName().equals(person.getName()));

    	 // height加了transient,不会被序列化
        System.out.println(p2.getHeight()); // 0
        System.out.println(p2.getHeight() == person.getHeight()); //False
    }
}

下面说下共通之处,共有三点,血肉苦弱,机械飞升,借助外在的设备,将人的信息持久的保存起来,等到以后有了合适的科学条件,再把个人的信息下载到新的皮囊里,那么很显然,你能上传的只有思维,你怎么知道上传的思维经过数百年数千年的变化后,与你上传前的东西一致,而不是与之相似的另一个双胞胎的思维呢?这就是serialVersionUID的作用,这是第一点;你的一切骨架和其它硬件都被抛弃了,这就是static变量不会被初始化的道理,因为下一幅皮囊还有,这是第二点;你不想留给下辈子的记忆也可以选择性抛弃,这就是Java中的transient关键字所做的,不想要被序列化的东西不要,这是第三点

参考文章或视频链接
[1] Serialization and Deserialization in Java with Example
[2] Introduction to Java Serialization
[3] 《Java类成员默认访问控制权限是default》
[4] JUnit 5 Tutorial: Exploring New Features and Changes
[5] Java Object Serialization Specification: 4 - Class Descriptors - Oracle
[6] What Is the serialVersionUID?
[7] transient keyword in Java

你可能感兴趣的:(Java技术栈,java)