java基础序列化、反序列化和transient的作用

一、概念

为什么会有序列化?平时我们所说的java内存中的对象是无法进行网络通信和IO操作的,对象将以序列化的存储状态(表现形式)被它们所识别。

  1. 序列化:将一个对象转换成一串二进制表示的字节数组,通过保存或转移这些字节数组达到持久化的目的。
  2. 反序列化:将字节数组重组成对象。

二、实现

序列化只需要实现java.io.Serializable接口就可以了。序列化的时候有一个serialVersionUID参数,Java序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化,Java虚拟机会把传过来的字节流中的serialVersionUID和本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的实体类,可以进行反序列化,否则Java虚拟机会拒绝对这个实体类进行反序列化并抛出异常。

serialVersionUID有两种生成方式:

  1. 默认的1L。
  2. 根据类名、接口名、成员方法以及属性等来生成一个64位的Hash字段。

Java为用户定义了默认的序列化、反序列化方法,其实就是ObjectOutputStream的defaultWriteObject方法和ObjectInputStream的defaultReadObject方法。

实例:

import lombok.Data;

import java.io.*;

/**
 * 序列化
 *
 * @author wangmaoyu
 * @create 2018-06-06 11:33
 **/
@Data
public class SerializableObject implements Serializable {
    private String str1;
    private transient String  str2;
    private static  String str3="abc";

    public SerializableObject(String str1, String str2) {
        this.str1 = str1;
        this.str2 = str2;
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        File file = new File("f:" + File.separator + "s.txt");
        OutputStream outputStream = new FileOutputStream(file);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(new SerializableObject("str1","str2"));
        objectOutputStream.close();

        FileInputStream fileInputStream = new FileInputStream(file);
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        SerializableObject serializableObject= (SerializableObject) objectInputStream.readObject();
        System.out.println(serializableObject.getStr1());
        System.out.println(serializableObject.getStr2());
        objectInputStream.close();
    }
}

结果,变量str2为null,说明以下3点:

  1. 序列化之后保存的是对象的信息。
  2. 被声明为transient的属性不会被序列化,这就是transient关键字的作用。
  3. 被声明为static的属性不会被序列化,这个问题可以这么理解,序列化保存的是对象的状态,但是static修饰的变量是属于类的而不是属于对象的,因此序列化的时候不会序列化它。

三、总结

  1. 当父类继承Serializable接口时,所有子类都可以被序列化
  2. 子类实现了Serializable接口,父类没有,父类中的属性不能序列化(不报错,数据丢失),但是在子类中属性仍能正确序列化。
  3. 如果序列化的属性是对象,则这个对象也必须实现Serializable接口,否则会报错。
  4. 反序列化时,如果对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错。
  5. 反序列化时,如果serialVersionUID被修改,则反序列化时会失败。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值