串行化
什么是串行化?
- 其实Java序列化和Java串行化都是一样的,都对应英文中的Serializable。
- 一个对象随着创建而存在,随着程序结束而结束。那如果我要保存一个对象的状态呢?Java序列化能够将对象的状态写入byte流存储起来,也从其他地方将byte流读取出来,重新构造一个新的对象。这种机制允许你将对象通过网络进行传播,并且可以随时把对象持久化到数据库、文件系统中。简而言之,序列化就是将一个对象的状态保存起来,而反序列化就是将已经保存的流对象恢复成原来的对象。
如何实现序列化?
- 实现序列化有一个条件,即实现序列化的类必须实现java.io.Serializable接口。之后可以利用ObjectInputStream的readOjbect()方法和OjbectOutputStream的writeObject()方法进行对象的读和写,即反序列化和序列化。
- 串行化只能保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符都不能保存。
- serialVersionUID 是对每个对象生成一个唯一id,一旦对象被改动,serialVersionUID 也应该随之改动。
public class User implements Serializable {
private static final long serialVersionUID = -7456133723670163623L;
private String name;
private int age;
private String color;
private String partner;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getPartner() {
return partner;
}
public void setPartner(String partner) {
this.partner = partner;
}
}
public class TestSeria {
/**
* 串行化user对象
* @throws Exception
*/
@Test
public void test1() throws Exception{
FileOutputStream fos = new FileOutputStream("F:/serializable/user.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
User dog = new User();
oos.writeObject(dog);
oos.close();
fos.close();
}
/**
* 反串行化user对象
* @throws Exception
*/
@Test
public void test2() throws Exception {
FileInputStream fis = new FileInputStream("F:/serializable/user.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
User d = (User)ois.readObject();
d.setName("aaa");
d.setColor("bbb");
d.setAge(33);
System.out.println(d.getName());
System.out.println(d.getAge());
System.out.println(d.getColor());
ois.close();
fis.close();
}
}
串行化和深度拷贝
- java 对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用 对象序列化可以进行对象的“深复制”,即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
transient在串行化中的作用
- 将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
- transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
- 一个静态变量不管是否被transient修饰,均不能被序列化。
其它
- 不是每个类都可序列化,有些类是不能序列化的, 例如涉及线程的类与特定JVM有非常复杂的关系。