【技术累积】【点】【java】【21】序列化二三事

基础概念

  • 把对象等转为二进制进行传输的是序列化,反之为反序列化;
  • 应用场景通常为读写文件,传输数据/接口调用;

Externalizable和Serializable

java的序列化方式有两种;html

Serializable是经常使用的方法,实现方法为java

class User implements Serializable {
        private static final long serialVersionUID = -3226152074589523662L;
       ...
    }

实现接口,而且最好有序列化ID;ide

Externalizable是Serializable的子类,但不会自动化序列化,须要调用方法实现序列化;函数

idea自动生成序列化ID

打开设置中的检测,而后每次有须要序列化的,生成一个Long型便可加密

Intellij idea用快捷键自动生成序列化ididea

序列化ID也能够是自定义的,好比简单的1L,只要调用方和被调用方约定一致便可;.net

transient关键字

  • transient修饰的变量,不会被序列化;
  • 静态变量必定不会被序列化(类的属性而不是对象的属性值)
  • 一旦变量被transient修饰,变量将再也不是对象持久化的一部分,该变量内容在序列化后没法得到访问;
  • transient关键字只能修饰变量,而不能修饰方法和类;
  • 使用Externalizable能够序列化transient修饰的变量
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.testng.annotations.Test;

import java.io.*;

@Slf4j
public class TestTransient {

//    private static final long serialVersionUID = 8204877978271765366L;

    @Test
    public void testTransi(){
        User user = new User("andy","123456");
        log.info("Before serializable,user={}",user.toString());
        try {
            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("D:/user.txt"));
            os.writeObject(user);
            os.flush();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {

            ObjectInputStream is = new ObjectInputStream(new FileInputStream("D:/user.txt"));
            user = (User) is.readObject();
            is.close();
            log.info("After serializable,username={},pwd={}",user.getUsername(),user.getPassword());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    @Setter
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    static class User implements Serializable {
        private static final long serialVersionUID = -3226152074589523662L;
        String username;
        transient String password;
    }
}

还须要注意的几个问题

  • 虚拟机是否容许反序列化,不只取决于类路径和功能代码是否一致,一个很是重要的一点是两个类的序列化 ID 是否一致
  • 要想将父类对象也序列化,就须要让父类也实现Serializable 接口。若是父类不实现的话的,就须要有默认的无参的构造函数
  • 能够尝试使用序列化实现加密控制等(Override),参考RMI技术
  • 注意往一个文件中屡次写入同一个对象的状况code

    Java 序列化机制为了节省磁盘空间,具备特定的存储规则,当写入文件的为同一对象时,并不会再将对象的内容进行存储,而只是再次存储一份引用,上面增长的 5 字节的存储空间就是新增引用和一些控制信息的空间。反序列化时,恢复引用关系,使得清单 3 中的 t1 和 t2 指向惟一的对象,两者相等,输出 true。该存储规则极大的节省了存储空间。htm

参考文章

相关文章
相关标签/搜索