Java学习-IO流-序列化流

Java学习-IO流-序列化流

                 字节流
             ↙         ↘
   InputStream         OutputStream
        ↓                   ↓
    反序列化流            序列化流
ObjectInputStream    ObjectOutputStream

序列化流

序列化流/对象操作输出流:把java中的对象写到本地文件中
public ObjectOutputStream(OutputStream out):把基本流包装成高级流
public final void writeObject(Object obj):把对象序列化(写)到文件中

public class Student {
	private String name;
	private int age;
}
Student stu = new Student("zhangsan",23);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("..\\xx.txt"));
oos.writeObject(stu);
oos.close();
//报错:NotSerializableException

解决方案:让Javabean类实现Serializable接口,没有抽象方法,标记型接口,一旦实现了这个接口,就表示当前的类可以被序列化

public class Student implements Serializable{
	private String name;
	private int age;
}
Student stu = new Student("zhangsan",23);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("..\\xx.txt"));
oos.writeObject(stu);
oos.close();

反序列化流

反序列化流/对象操作输入流:把序列化到本地文件的对象数据读取到程序中
public ObjectInputStream(InputStream in):把基本流包装成高级流
public Object readObject():把序列化到本地文件中的对象读取到程序中

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("..\\xx.txt"));
Object o = ois.readObject();
sout(o);
ois.close();

序列化流和反序列化流使用细节

版本号

将 Student 类对象 stu 序列化到本地文件后,在 Student 类中新增属性 address

public class Student implements Serializable{
	private String name;
	private int age;
	private String address;
}

再将 stu 反序列化到程序中时会报错
分析原因:
在类实现 Serializable 接口时,java 会根据类的属性、方法等信息计算一个 long 类型序列号,在类实例化时,对象会包含这个序列号,在对象序列化时,序列号也一起被写到本地文件中;在类新增属性后,会重新计算版本号,导致反序列化时两个版本号不一致,因此会报错
解决方案:
固定版本号
法1:

public class Student implements Serializable{
	private static final long serialVersionUID=1L;
	private String name;
	private int age;
}

法2:
File → Settings → 搜索 Serializable → 选中Serializable class without ‘serialVersionUID’ → 选中Transient field is not initialized deserialization → OK
未定义序列号的类会被标记,鼠标悬停时会提示:does not define a ‘serialVersionUID’ field,选中类,Alt + 回车 → Add ‘serialVersionUID’ field,自动计算版本号

@Serial
private static final long serialVersionUID = -123456789L;

验证效果
定义类

public class Student implements Serializable{
	private static final long serialVersionUID = -123456789L;
	private String name;
	private int age;
}

序列化对象

Student stu = new Student("zhangsan",23);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("..\\xx.txt"));
oos.writeObject(stu);
oos.close();

修改类属性

public class Student implements Serializable{
	private static final long serialVersionUID = -123456789L;
	private String name;
	private int age;
	private String address;
}

反序列化

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("..\\xx.txt"));
Object o = ois.readObject();
sout(o);
ois.close();

输出:Student{name=‘zhangsan’,age=23,address=‘null’}

限制某些属性不被序列化到本地文件

transient:瞬态关键字,不会把它修饰的属性序列化到本地文件

public class Student implements Serializable{
	private static final long serialVersionUID = -123456789L;
	private String name;
	private int age;
	private transient String address;
}

序列化对象

Student stu = new Student("zhangsan",23,"天津");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("..\\xx.txt"));
oos.writeObject(stu);
oos.close();

反序列化

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("..\\xx.txt"));
Object o = ois.readObject();
sout(o);
ois.close();

输出:Student{name=‘zhangsan’,age=23,address=‘null’}

小结

1.类应实现 Serializable 接口,否则报错 NotSerializableException
2.序列化到本地文件中的数据是不能被修改的,一旦修改无法读取
3.序列化后,修改了类,再反序列化,会报错:InvalidClassException,解决方案:SerialVersionUID
4.transient:限制某个属性不参与实例化过程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值