Java第十八天(一)
序列化流(对象流Serializable)
定义:将对象以流的形式存储在硬盘上或者数据库中的过程就是写序列化流。
反序列化:从硬盘或数据库中读取的过程就是反序列化。
对象输出流(ObjectOutputStream)
定义:ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。(序列化过程)
如果想要序列化某个对象,那么这个对象要实现Serializable接口。
写入到文本文件中的字符我们读不懂,也不需要读懂。
常用构造器
ObjectOutputStream(OutputStream out)
创建一个写入指定的OutputStream的ObjectOutputStream。 (持久化对象)
持久化对象方法
void writeObject(Object obj)
将指定的对象写入ObjectOutputStream。
序列化(持久化对象)用法(将对象存储到硬盘或数据库中)
Student类
/**
* Student类
*/
public class Student implements Serializable{
//定义学生类成员变量
private Integer id;
private String name;
private Integer age;
/*
* 封装学生类的成员变量
*/
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
//生成相应的构造器
public Student(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
//重写toString方法
@Override
public String toString() {
return "Student [学号=" + id + ", 姓名=" + name + ", 年龄=" + age + "]"+" ";
}
}
序列化(持久化对象)类
public class SerialDemo {
public static void main(String[] args) {
writeObject();
}
public static void writeObject() {
// 创建序列化对象输出流对象
ObjectOutputStream oos = null;
try {
// 创建输出流对象
oos = new ObjectOutputStream(new FileOutputStream("Test1.txt"));
Student s = new Student(15,"张三",20);
oos.writeObject(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(oos != null) {
oos.close();
}
} catch (IOException e) {
}
}
}
}
对象输入流(ObjectInputStream)
ObjectInputStream对先前使用ObjectOutputStream编写的基本数据和对象进行反序列化。(反序列化过程)
常用构造器
ObjectInputStream(InputStream in)
创建从指定的InputStream读取的ObjectInputStream。
读取对象方法
Object readObject()
从ObjectInputStream读取一个对象。
反序列化(读取对象)用法(从硬盘或数据库中读取对象)
注意:每当持续化一个对象时,Java同时都会赋予一个serialVersionUID(序列化版本号)。当写入与读取发生UID不匹配时就会报错,所以我们需要自动生成一个serialVersionUID,这样即使对象类发生了变化也不会影响反序列化。
自动生成serialVersion(序列化版本号)方法:
Student类
/**
* Student类
*/
public class Student implements Serializable{
/**
* 自动给类一个序列化版本号,即使类发生了变化也不会影响反序列化
*/
private static final long serialVersionUID = -7068496636765082214L;
//定义学生类成员变量
private Integer id;
private String name;
private Integer age;
/*
* 封装学生类的成员变量
*/
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
//生成相应的构造器
public Student(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
//重写toString方法
@Override
public String toString() {
return "Student [学号=" + id + ", 姓名=" + name + ", 年龄=" + age + "]"+" ";
}
}
反序列化类
public class SerialDemo {
public static void main(String[] args) {
readObject();
}
public static void readObject() {
// 创建对象输入流对象
ObjectInputStream ois = null;
try {
// 创建字节输入流对象
ois = new ObjectInputStream(new FileInputStream("Test1.txt"));
// 读取到Object类型的对象,并将其强转为Student类型
Student s = (Student)ois.readObject();
System.out.println(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
if(ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
集合序列化
当读取到最后一个已持久对象再向后读取时,返回值并不是null,而是直接报EOFException。EOF表示读到了文件尾,并且后面已经没有内容可以读了。
由于ArrayList已经实现了Serializable接口,所以我们可以直接使用ArrayList进行写入。
Student类
/**
* Student类
*/
public class Student implements Serializable{
/**
* 自动给类一个序列化版本号,即使类发生了变化也不会影响反序列化
*/
private static final long serialVersionUID = -7068496636765082214L;
//定义学生类成员变量
private Integer id;
private String name;
private Integer age;
/*
* 封装学生类的成员变量
*/
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
//生成相应的构造器
public Student(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
//重写toString方法
@Override
public String toString() {
return "Student [学号=" + id + ", 姓名=" + name + ", 年龄=" + age + "]"+" ";
}
使用数组序列化 反序列化对象
public class SerialArrayDemo {
public static void main(String[] args) {
// 先执行写入
writeObject();
// 写入执行完毕后再执行读取
readObject();
}
public static void writeObject() {
// 创建序列化对象输出流对象
ObjectOutputStream oos = null;
try {
// 创建输出流对象
oos = new ObjectOutputStream(new FileOutputStream("Test1.txt"));
// 使用List也可以用来存储对象
List<Student> stuArray = new ArrayList<Student>();
stuArray.add(new Student(23,"张三",20));
stuArray.add(new Student(17,"李四",25));
stuArray.add(new Student(45,"王五",29));
stuArray.add(new Student(21,"韩六",30));
oos.writeObject(stuArray);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(oos != null) {
oos.close();
}
} catch (IOException e) {
}
}
}
public static void readObject() {
// 创建对象输入流对象
ObjectInputStream ois = null;
try {
// 创建字节输入流对象
ois = new ObjectInputStream(new FileInputStream("Test1.txt"));
// 读取到Object类型的对象,并将其强转为Student类型
ArrayList<Student> stuArray = (ArrayList<Student>)ois.readObject();
// 使用外置比较器将序列集合排序
// stuArray.sort(new StuComparator());
// 使用增强for循环打印
for(Student s:stuArray){
System.out.println(s);
}
// 或者直接打印ArrayList
System.out.println(stuArray);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
if(ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
外置比较器类
public class StuComparator implements Comparator<Student> {
@Override
public int compare(Student stu1, Student stu2) {
//先比较学号
int val = stu1.getId() - stu2.getId();
if(val == 0) {
//若学号相同比较年龄
val = stu1.getAge() - stu2.getAge();
if(val == 0) {
//判断两个对象的姓名是否为空
if(stu1.getName() != null && stu2.getName() != null) {
//若学号、年龄都相同,比较姓名
val = stu1.getName().compareTo(stu2.getName());
}
}
}
return val;
}
}