Java 序列化
序列化定义
-
序列化是一种处理对象流的机制。
-
对象流是将对象的内容流化,可以对流化后的对象进行读写操作,也可以对流化后的对象进行网络传输。
-
序列化是为了解决在对对象流进行读写操作时可能引发的问题。
实现序列化、反序列化
1、一般通过 实现 serializable 实现
使用一个输出流 (字符流、字节流)来构造一个 ObjectOutputStream
对象流
objectOutputStream.writeObject(student); //序列化
使用一个输出流 (字符流、字节流)来构造一个 ObjectInputStream
对象流
Student student = (Student) objectInputStream.readObject(); // 反序列化
2、 还可以实现 Externalizable
实现
public class Student implements Serializable {
String name;
int age;
String gender;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
}
/**
* 序列化
*/
private static void serialize(String path) {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream(path);
oos = new ObjectOutputStream(fos);
Student student = new Student("lucas", 20, "male");
System.out.println("序列化 ==> " + student);
oos.writeObject(student);
oos.flush();
oos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 反序列化
*/
private static void unSerialize(String path) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream(path);
ois = new ObjectInputStream(fis);
Student student = (Student) ois.readObject();
System.out.println("反序列化 ==> " + student);
ois.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
持久化的作用
Java 允许在内存中创建可复用的对象,但一般情况下,只有 jvm 运行时,这些对象才可能存在,这些对象的生命周期不会比 jvm 的生命周期更长。但在现实应用中,可能要求在 jvm 停止运行之后能够保存持久化的对象,并在将来重新读取被保存的对象。
Java 序列化就能延长持久化对象的生命周期!
序列化特点
1、持久化对象时,会把对象的成员变量保存为一组字节,使用时再将字节组装成对象
2、不会持久化的静态变量
3、不会持久化 transient 修饰的变量
public class Person implements Serializable {
public static String ATTR = "";
private String name;
private transient String age;
public Person() {
}
}
- 序列化和反序列化中间没有修改过静态变量,会读取到 jvm 缓存的值,看起来像是也持久化了静态变量
private static void test2() {
String path = "person.txt";
Person person = new Person();
Person.ATTR = "person";
person.setName("Joe");
System.out.println("attr : " + Person.ATTR);
System.out.println("name : " + person.getName());
serialize(path, person);
Person person1 = (Person) unSerialize(path);
System.out.println("attr : " + Person.ATTR);
System.out.println("name : " + person1.getName());
}
- 序列化和反序列化中间修改过静态变量
private static void test3() {
String path = "person.txt";
Person person = new Person();
person.setName("Joe");
person.setAge("20");
Person.ATTR = "person";
System.out.println("attr : " + Person.ATTR);
System.out.println("name : " + person.getName());
System.out.println("age : " + person.getAge());
serialize(path, person);
Person.ATTR = "person1";
Person person1 = (Person) unSerialize(path);
System.out.println("attr : " + Person.ATTR);
System.out.println("name : " + person1.getName());
System.out.println("age : " + person1.getAge());
}
拓展
public class User1 implements Externalizable {
private String username;
private transient String id;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(id);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
id = (String) in.readObject();
}
}
private static void test1() throws IOException, ClassNotFoundException {
User1 user = new User1();
user.setUsername("yes");
user.setId("water");
ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream(new File("user1")));
objectOutput.writeObject(user);
ObjectInput objectInput = new ObjectInputStream(new FileInputStream(new File("user1")));
user = (User1) objectInput.readObject();
System.out.println(user.getUsername());
System.out.println(user.getId());
objectOutput.close();
objectInput.close();
}
transient 关键字
1)transient修饰的变量不能被序列化;
2)transient只作用于实现 Serializable 接口;
3)transient只能用来修饰普通成员变量字段;
4)不管有没有 transient 修饰,静态变量都不能被序列化;