import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* 1、java.io.NotSerializableException
* 不支持序列化异常
*
* 2、参与序列化和反序列化的对象,必须实现Serialize接口
* 3、通过源代码发现:Serializable接口只是一个标志接口:
* public interface Serializable {
* }
* 接口里没有代码,作用:
* 起到标识的作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇
* Serializable是给java虚拟机看的,看到之后会自动生成一个序列化版本号
*
* 4、序列化版本号用处:
* java.io.InvalidClassException: Student; 无效的类异常
* local class incompatible:
* stream classdesc serialVersionUID = -426663630608197879, (Student类修改后,加了一个int a)
* local class serialVersionUID = 1754359514922040287 (Student类修改前)
*
* java语言中是采用什么机制来区分类的?
* 1、首先是根据类型进行比对,如果类名不一样,肯定不是同一个类
* 2、如果类名一样,通过类的序列化版本号进行区分
*
* 优点:两个名字相同的类,内容不一样,(不同的人写的),对于JVM来说,是可以区分的
* 因为这两个类都实现了Serializable接口,都有默认的序列化版本号,版本号不一样,就区分开了
*
* 缺陷:一旦代码确定,就不能就行修改,只要修改,就会重新编译,生成新的序列化版本号
* 这个时候java虚拟机就会认为是一个全新的类
*
* 所以怎样修改呢??
* 写一个固定不变的序列号,即使以后代码修改,但版本号不变,java虚拟机会认为是同一个类
*
* 一次序列化多个对象?
* 可以,可以将对象放到集合中,序列化集合
* 注意:参与序列化的ArrayList集合以及集合中的元素都需要实现java.io.Serializable接口
*
* 疑问:怎么讲解的是不能存储第二个对象?
* 实验的是,可以存储第二个对象,也可以读出来,再存进去个集合,也可以读出来(这里不用for循环)
* 单纯Object obj = aa.readObject() sout(obj)
*
*/
public class ObjectOutputStreamTest {
public static void main(String[] args) {
Student student = new Student(111,"zhangsan");
//序列化多个对象;
List<Student> ss = new ArrayList<>();
ss.add(new Student(222,"lisi"));
ss.add(new Student(333,"wangwu"));
ss.add(new Student(444,"zhaoliu"));
Student sss = new Student(555,"agrfwrg");
ObjectOutputStream oos = null;
try {
//序列化
oos = new ObjectOutputStream(new FileOutputStream("myfile333"));
//序列化对象
oos.writeObject(student);
oos.writeObject(ss);
//oos.writeObject(ss);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;
/**
*
* 反序列化
*
* 刚开始写的myfile333,文件里的是Student,然后又向里面写了一个集合,
* sout输出oos.readObject() instanceof Student 是true 换为List就是false
* 因为这个文件被保留了,里面的对象也是,所以要么删除内容,要么新建一个文件,写这个集合
*
* 结论:存多个对象会报错,用List集合进行存储
*
*/
public class ObjectInputStreamTest {
public static void main(String[] args) {
ObjectInputStream oos = null;
try {
oos = new ObjectInputStream(new FileInputStream("myfile333"));
//开始反序列化
//Object obj = oos.readObject();
//System.out.println(oos.readObject() instanceof Student);
//List<Student> obj = (List<Student>) oos.readObject();
Object obj = oos.readObject();
System.out.println(obj);
Object obj02 = oos.readObject();
System.out.println(obj02);
/*for(Student ss : obj) {
System.out.println(ss);
}*/
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
import java.io.Serializable;
/*
* transient 游离的,不参与序列化*/
public class Student implements Serializable {
private int age;
private transient String name;
int a ;
//建议手动写,不建议自动生成,随意写就行,冲突概率很低,首先类名相同的情况下,才会通过序列化版本号进行比对
private static final long serialVersionUID = 1L;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public Student() {
}
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;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}