java序列化和反序列化,java序列化序列化
分享于 点击 9166 次 点评:56
java序列化和反序列化,java序列化序列化
什么是java的序列化
所谓java对象的序列化就是将java对象的状态转换为字节流的过程,反序列化则是将字节流恢复成java对象的过程。
为什么要java的序列化
java的序列化主要为了java对象在网络中传输和持久化使用。
需要在网络中传输的java对象必须要经过序列化转换为二进制才能传输。比如一个java服务向异地的另一个服务发送请求,请求参数是一个java对象,通过将这个对象序列化成字节流后经过网络传输到另一个服务器,接收服务器在收到请求后通过反序列化再将字节流还原成java对象,像RMI、Socket通信等都需要用到java对象的序列化。
在因为某个对象太大又不经常使用,为了节约内存空间,或者对象保存的状态非常重要,需要在服务重启后也能可恢复等等这些情况, 经常需要java对象持久化,而这些持久化的对象也需要进行序列化处理才能持久化到文件。
如何实现序列化
序列化对象的类必须实现Serializable或Externalizable。其中Externalizable是Serializable的子接口,区别是:
说明:java中提供transient关键字,主要为我们提供便利,只要实现Serilizable接口,在不需要序列化的属性前添加关键字transient即可,不用像实现Externalizable的类,还需要为序列化以及不序列化哪些字段写一些代码进行定制。对象流
java通过java.io中的两个类ObjectOutputStream和ObjectInputStream两个类来实现对象与字节流之间的转换,通过ObjectOutputStream类将对象序列化成字节流,再通过ObjectInputStream将字节流反序列化成对象。 writeObject()方法是ObjectOutputStream中最重要的方法,用于对象序列化。如果对象包含其他对象的引用,则writeObject()方法递归序列化这些对象。readObject()方法是ObjectInputStream中最重要的方法,用于对象反序列化。
举例说明
实现Serializable序列化
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class PersonTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
File file = new File("d:\\person.xml");
ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file));
Person person = new Person("Mahesh","man", true, 20);
oout.writeObject(person);
oout.close();
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
Person newPerson = (Person) oin.readObject();
oin.close();
System.out.println(newPerson);
System.out.println("person == newPerson:"+ (person == newPerson));
}
}
class Person implements Serializable{
private static final long serialVersionUID = 1L;
public String name;
private String sex;
private transient boolean isMarried;
private transient int age;
public Person() {
}
public Person(String name, String sex, boolean isMarried, int age) {
this.name = name;
this.sex = sex;
this.isMarried = isMarried;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", sex=" + sex + ", isMarried="
+ isMarried + ", age=" + age + "]";
}
}
执行结果如下:
Person [name=Mahesh, sex=man, isMarried=false, age=0]
person == newPerson:false
从结果可以看出Person对象的name字段和sex字段被序列化,而被transient修饰的字段的状态则没有被序列化。
实现Externalizable序列化
import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class PersonTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
File file = new File("d:\\person.xml");
ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file));
Person student1 = new Person("Mahesh","man", true, 20);
oout.writeObject(student1);
oout.close();
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
Person newPerson = (Person) oin.readObject();
oin.close();
System.out.println(newPerson);
}
}
class Person implements Externalizable{
private static final long serialVersionUID = 1L;
public String name;
private String sex;
private boolean isMarried;
private transient int age;
public Person() {
}
public Person(String name, String sex, boolean isMarried, int age) {
this.name = name;
this.sex = sex;
this.isMarried = isMarried;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", sex=" + sex + ", isMarried="
+ isMarried + ", age=" + age + "]";
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.name);
out.writeObject(this.sex);
out.writeInt(this.age);
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
//注意read数据的顺序和write数据的数据要一致,否则反序列化的字段状态将会乱掉
this.name = (String) in.readObject();
this.sex = (String) in.readObject();
this.age = in.readInt();
}
}
执行结果如下:
Person [name=Mahesh, sex=man, isMarried=false, age=20]
从执行结果可知实现Externalizable的类对象,序列化哪些字段是由在writeExternal()方法中定制的的,反序列化哪些字段是在readExternal()方法中定制的;无论字段是否被transient修饰,都可以由定制决定是否序列化和反序列化。
readResolve()方法
package com.yiibai.xstream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class PersonTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
File file = new File("d:\\person.xml");
Person person = Person.getInstance();
ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file));
oout.writeObject(person);
oout.close();
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
Person newPerson = (Person) oin.readObject();
oin.close();
System.out.println(newPerson);
System.out.println("person == newPerson:" + (person == newPerson));
}
}
class Person implements Serializable{
private static final long serialVersionUID = 1L;
public String name;
private String sex;
private transient boolean isMarried;
private transient int age;
private static Person person;
private Person(String name, String sex, boolean isMarried, int age) {
this.name = name;
this.sex = sex;
this.isMarried = isMarried;
this.age = age;
}
public synchronized static Person getInstance(){
if (null == person){
person = new Person("Long", "man", true, 23);
}
return person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", sex=" + sex + ", isMarried="
+ isMarried + ", age=" + age + "]";
}
}
执行结果:
Person [name=Long, sex=man, isMarried=false, age=0]
person == newPerson:false
上面Person类是单例模式,但是序列化之前和反序列化之后的对象却不是同一个。如何在反序列化的过程中保证单例模式呢呢?java提供了一个私有方法readResolve(),当JVM从内存中反序列化地"组装"一个新对象时,就会自动调用这个 readResolve方法来返回我们指定好的对象了, 单例规则也就得到了保证.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class PersonTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
File file = new File("d:\\person.xml");
Person person = Person.getInstance();
ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file));
oout.writeObject(person);
oout.close();
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
Person newPerson = (Person) oin.readObject();
oin.close();
System.out.println(newPerson);
System.out.println("person == newPerson:" + (person == newPerson));
}
}
class Person implements Serializable{
private static final long serialVersionUID = 1L;
public String name;
private String sex;
private transient boolean isMarried;
private transient int age;
private static Person instance;
private Person() {
}
private Person(String name, String sex, boolean isMarried, int age) {
this.name = name;
this.sex = sex;
this.isMarried = isMarried;
this.age = age;
}
public synchronized static Person getInstance(){
if (null == instance){
instance = new Person("Long", "man", true, 23);
}
return instance;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", sex=" + sex + ", isMarried="
+ isMarried + ", age=" + age + "]";
}
private Object readResolve() {
return instance;
}
}
执行结果如下:
Person [name=Long, sex=man, isMarried=true, age=23]
person == newPerson:true
相关文章
- 暂无相关文章
用户点评