目录
序列化是做什么的
对象的生命周期常随着生成该对象的程序的终止而终止,有时候需要把内存中的各种对象状态
(也就是实例变量,不是方法)保存下来并且可以在需要时再将对象恢复.虽然你可以用你自己的
方法保存对象的状态,但是java提供了一种应该比我们好的保存对象状态的机制,那就是序列化
什么情况下需要序列化?
1.当你想要把内存中的对象状态保存到一个文件中或者数据中的时候
2.当你想用套接字在网络上传送对象的时候
3.当你想要通过RMI传输对象的时候
当对一个对象实现序列化时,究竟发生了什么?
在没有序列化前,每个保存在堆中的对象都有相应的状态,即实例变量
比如:
Person p = new Person();
p.setName("lisi");
p.setAge(23);
当通过下面的代码序列化之后,Person对象中的name和age实例变量的值("lisi",23)都被保存到p.ser文件中,这样以后又可以把它从文件中读取出来,重新在堆中创建原来的对象.当然保存时不仅仅是保存对象的实例变量的值
JVM还要保存一些别的特殊信息.
FileOutputStream fs = new FileOutputStream("p.ser");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(p);
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Person implements Serializable{
/**
*
*/
private static final long serialVersionUID = -7970005053591210082L;
private String name ;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public static void main(String[] args) {
Person p = new Person();
p.setName("yinlele");
p.setAge(23);
try {
FileOutputStream fis = new FileOutputStream("p.ser");
ObjectOutputStream oos = new ObjectOutputStream(fis);
oos.writeObject(p);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
打开p.ser文件之后的信息
注意事项:
1).序列化时,只对对象的状态保存,而不管对象的方法
2).当一个父类实现序列化时,子类自动序列化,不需要显式实现Serializable接口
3).当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象序列化.
4).并非所有的对象都可以序列化.(遇到在补充)
为什么java需要进行序列化
java序列化:一特定的方式对类实例的瞬时状态进行编码保存的一种操作.
序列化作用的对象是类的实例,对实例进行序列化,就是保存实例当前在内存中的状态,包括实例的每一个属性的值和引用
反序列化,是将序列化的编码解码成类实例的瞬时状态
序列化就是为了保存java类的对象状态.保存这个状态的作用主要用于不同jvm之间进行类实例间的共享,在ORMaping中的缓存机制,进行缓存同步时,便是常见的java序列化的应用之一.在进行远程方法调用,远程过程调用时,采用序列化对象的传输也是一种应用...当你想从一个jvm中调用另一个jvm的对象时,你就可以考虑使用序列化了.
总之:序列化的作用就是为了不同jvm之间共享实例对象的一种解决方案,由java提供此机制,效率之高,
是其他解决方案无法比拟的.
transient关键字
经常在实现了 Serializable接口的类中能看见transient关键字。这个关键字并不常见。 transient关键字的作用是:阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。
当某些变量不想被序列化,同是又不适合使用static关键字声明,那么此时就需要用transient关键字来声明该变量。
例如用 transient关键字 修饰age变量
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Person implements Serializable{
/**
*
*/
private static final long serialVersionUID = -7970005053591210082L;
private String name ;
transient private Integer age;
private Gender gender;
public Person() {
super();
}
public Person(String name, Integer age, Gender gender) {
super();
this.name = name;
this.age = age;
this.gender = gender;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Person [name=");
builder.append(name);
builder.append(", age=");
builder.append(age);
builder.append(", gender=");
builder.append(gender);
builder.append("]");
return builder.toString();
}
public static void main(String[] args) throws Exception {
File file = new File("person.out");
ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file));
Person person = new Person("yinlele", 23, Gender.MALE);
oout.writeObject(person);
oout.close();
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
Object newPerson = oin.readObject(); // 没有强制转换到Person类型
oin.close();
System.out.println(newPerson);
//Person [name=yinlele, age=23, gender=MALE] 不加transient
//Person [name=yinlele, age=null, gender=MALE]//加上 transient
}
以上只是为自己以后用到的时候方便,做个记录