1、java.io.NotSerializableException:
2、参与序列化和反序列化的对象,必须实现Serializable接口。
3、注意:通过源代码发现,Serializable接口只是一个标志接口:
public interface Serializable {
}
这个接口当中什么代码都没有。
那么它起到一个什么作用呢?
起到标识的作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。
Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成
一个序列化版本号。
4、序列化版本号有什么用呢?
java.io.InvalidClassException:
com.bjpowernode.java.bean.Student;
local class incompatible:
stream classdesc serialVersionUID = -684255398724514298(十年后),
local class serialVersionUID = -3463447116624555755(十年前)
java语言中是采用什么机制来区分类的?
张三编写了一个类:com.bjpowernode.java.bean.Student implements Serializable
李四编写了一个类:com.bjpowernode.java.bean.Student implements Serializable
不同的人编写了同一个类,但“这两个类确实不是同一个类”。这个时候序列化版本就起上作用了。
对于java虚拟机来说,java虚拟机是可以区分开这两个类的,因为这两个类都实现了Serializable接口,
都有默认的序列化版本号,他们的序列化版本号不一样。所以区分开了。(这是自动生成序列化版本号的好处)
思考:
这种自动生成序列化版本号有什么缺陷?
最终结论:
public class Student implements Serializable {
// IDEA工具自动生成序列化版本号。
//private static final long serialVersionUID = -7998917368642754840L;
// Java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号。
// 这里没有手动写出来,java虚拟机会默认提供这个序列化版本号。
// 建议将序列化版本号手动的写出来。不建议自动生成
private static final long serialVersionUID = 2280880218502988510L;// java虚拟机识别一个类的时候先通过类名,如果类名一致,再通过序列化版本号。
//private String name;
// 过了很久,Student这个类源代码改动了。
// 源代码改动之后,需要重新编译,编译之后生成了全新的字节码文件。
// 并且class文件再次运行的时候,java虚拟机生成的序列化版本号也会发生相应的改变。
int no;
String name;
private int age;
private String email;
private String address;
public Student(){}
public Student(int no,String name){
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
", name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
", address='" + address + '\'' +
'}';
}
}
public class ObjectOutputStreamTest01 {
public static void main(String[] args) {
//创建Student对象
Student s = new Student(1111,"zahngsan");
//序列化
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new FileOutputStream("students"));
//序列化对象
out.writeObject(s);
//刷新
out.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class ObjectInputStreamTest01 {
public static void main(String[] args) {
//反序列化
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("students"));
//反序列化
Object o = ois.readObject();
// 反序列化回来是一个学生对象,所以会调用学生对象的toString方法。
System.out.println(o);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally{
if(ois != null){
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
可以,可以将对象放到集合当中,序列化集合。
提示:
参与序列化的ArrayList集合以及集合中的元素User都需要实现 java.io.Serializable接口。
transient关键字表示游离的,不参与序列化。
public class User implements Serializable {
private static final long serialVersionUID = -203337022093748667L;
private int no;
// transient关键字表示游离的,不参与序列化。
private transient String name;// name不参与序列化操作!
public User() {
}
public User(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
public class ObjectOutputStreamTest02 {
public static void main(String[] args) {
//序列化多个对象,可以把对象放在集合中操作
List<User> list = new ArrayList<>();
list.add(new User(1111,"zhangsan"));
list.add(new User(2222,"lisi"));
list.add(new User(3333,"wangwu"));
list.add(new User(4444,"zhaoliu"));
//序列化集合
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("user"));
oos.writeObject(list);
//流刷新
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/*
反序列化集合
*/
public class ObjectInputStreamTest02 {
public static void main(String[] args) {
//反序列化
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("user"));
//反序列化
List<User> userList = (List<User>) ois.readObject();
//Object obj = ois.readObject();
//System.out.println(obj instanceof List);
//System.out.println(userList);
for(User users : userList){
System.out.println(users);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(ois != null){
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}