序列化是网络传输不可避免的问题,所以,想要进阶高级Java,弄懂网络通信,Java序列化知识是第一步。
- 序列化对象
/**
* 父类如果没有实现序列化接口,则其父类属性不会被保存在子类中,要想将父类对象也序列化,
* 就需要让父类也实现Serializable 接口。如果父类不实现的话的,就需要有默认的无参的构造函数。
* 而一个 Java 对象的构造必须先有父对象,才有子对象,反序列化也不例外。所以反序列化时,为了构造父对象,只能调用父类的无参构造函数作为默认的父对象。
* 在父类无参构造函数中对变量进行初始化。
*/
public class Person implements Serializable{//序列化只保存对象的状态,和类状态无关
private static final long serialVersionUID = 1L;//唯一标识该对象,如果序列化后对此值修改,反序序列化时报错,类似单向加密
private String name;
public static int age;//序列化并不保存静态变量
private transient String adress;//transient 变量不序列化
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [name=" + name + ", adress=" + adress + "]";
}
public static int getAge() {
return age;
}
public static void setAge(int age) {
Person.age = age;
}
public String getAdress() {
return adress;
}
public void setAdress(String adress) {
this.adress = adress;
}
}
- 序列化测试代码
public class Serialize {
public static void main(String[] args) throws Exception {
Person person = new Person();
person.setAdress("成都");
person.setName("小明");
Person.age=26;
serializePerson(person);
deserializePerson();
}
public static void serializePerson(Person person) throws Exception {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("person")));
oos.writeObject(person);
oos.flush();
System.out.println("第一次序列化成功,大小为"+new File("person").length());
//通过查看person二进制文件可知,只是最后追加了5个字节的引用
person.setName("小红");//反序列化后的名字并没有改变
oos.writeObject(person);
System.out.println("第二次序列化成功,大小为"+new File("person").length());
oos.close();
}
public static void deserializePerson() throws Exception {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("person")));
Person person = (Person)ois.readObject();
Person person1 = (Person)ois.readObject();
//Person person2 = (Person)ois.readObject();//序列化几次,则最多反序列化几次,否则报错 java.io.EOFException
System.out.println("两个对象是否是同一个:"+(person==person1));//true
Person.age=30;
System.out.println("反序列化结果"+person);//Person [name=小明, adress=null]
System.out.println("年龄:"+Person.age);
}
}
- 测试结果如下:
第一次序列化成功,大小为77 第二次序列化成功,大小为82 两个对象是否是同一个:true 反序列化结果Person [name=小明, adress=null] 年龄:30
通过查看person二进制文件可知,只是最后追加了5个字节的引用。当写入文件的为同一对象时,并不会再将对象的内容进行存储,而只是再次存储一份引用,上面增加的 5 字节的存储空间就是新增引用和一些控制信息的空间。