序列化就是把一个对象固化,怎么理解。java中一个对象,比如Person person = new Person(),通过new出一个person对象之后,如果你关闭了JVM(比如说关闭了eclipse),如果你还想用person对象怎么办?简单,我们重新new一个新的一模一样的对象,但是我们必须要上次new这个Person的属性,比如name,sex等,并且这个新new的对象也不可能一模一样的,因为他们是不同时间new出来的,也许这个时间间隔里面JVM还发生变化了呢。
所以我们需要有一种机制把person永久的保存下来,那就是序列化。通过什么办法序列化,我们最好理解的就是把person记录在一个文档里面(比如txt文件),这样子我下次使用就根据保存的这个txt文件通过程序再次读入程序就行了,这个过程就叫做反序列化。
请看示例,示例的目的是序列化一个Perosn对象,然后再反序列化回来。
定义person对象
package test.vo;
import java.io.Serializable;
/**
* 对象要想被序列化,必须实现Serializable接口
* @author tim.syh
*
*/
public class Person implements Serializable{
private static final long serialVersionUID = -7142264207488774373L;
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
序列化和反序列化
package test.serializable;
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 test.vo.Person;
public class TestSerializale {
public static void main(String[] args) throws Exception{
//定义一个person对象
Person person = new Person("tim", 20);
//序列化对象到path目录下,可以看到执行完成之后在D:/temp目录下多了一个person.txt文件
String path = "D:/temp/person.txt";
serialiobject(person, path);
//执行完上面的之后,你可以关闭掉eclipse甚至跑到你隔壁的电脑去执行反序列化的代码
//当然如果你要去隔壁电脑执行,需要把person.txt文件也拷贝过去哈
Person p = deSerialiobject("D:/temp/person.txt");
//打印下结果是 :Person [name=tim, age=20],perosn的信息又回来了。
System.out.println(p);
}
/**
* 序列化Person对象,生成的字节流存放path目录下去
* @param person
*/
private static void serialiobject(Person person, String path) throws Exception{
//jdk自带的序列化类,把person对象写入到path目录下的文件中
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(path));
oo.writeObject(person);
oo.close();
System.out.println("对象序列化成功");
}
/**
* 从文件中去读取对象。
* @param path 已经序列化的文件的目录
* @return Person对象
*/
private static Person deSerialiobject(String path) throws Exception{
//jdk自带的反序列化类,又把path路径下文件的内容读回成一个对象
ObjectInputStream oi = new ObjectInputStream(new FileInputStream(path));
Person p = (Person)oi.readObject();
oi.close();
System.out.println("对象反序列化成功!");
return p;
}
}
你可以自己做实验,当把一个对象序列化之后,你明天再来反序列化,还能够得到昨天新建对象person的信息,这是不是相当于把person这个对象的信息给固化了,这个让你想到了什么?对,ORM的概念,和这个是一样的意思。
作用
固化一个对象有什么用呢?这个用处可大了。
- 像示例中一样,可以把一个对象保存在硬盘中(就是各种文件呀),然后拿着它到处晃悠了。想用的时候再反序列化一下就又回来了。
- 把对象弄成文件之后就可以在网络上进行传输了,现在很流行的websercie首先就是要实现对象能够这样子序列化才行。
方式
序列化有很多方式,比如例子中说道的jdk自带的ObjectOutputStream对象(示例就是)啦,其他的第三方的比如比较常见的hessian,Google的Protocal Buffers呀,他们比jdk自带的效率高一些。其实还有更常用的方式那就是xml和json呀。
说到常用的xml和json,原来也是序列化的一种呀,当然是呀,一个xml和json文件的内容你都可以看成是一个个已经固话的对象,然后就可以进行保存,传输了,如果要用这些对象的时候反序列就OK了。
xml和json
在java web系统中,我们经常需要把person对象从A系统传到B系统进行处理,比如webservice这种远程调用,当然,他们已经帮我们实现了这部分网络传输的部分,对于我们来说,就相当是把person对象从A系统通过网络运输到B系统去了,但是实际它在运输之前,肯定要首先把person对象序列化成文本或者流的形式(就是二进制码,文本你要传输最终不也是要转成二进制进行传输吗)运送到B系统,B系统再进行反序列化从而拿到person对象。
SOUP协议就是用xml的形式传递对象数据,不过现在json越来越流行了,毕竟用xml来传递数据的soup协议比起轻量级的json来说,还是显得臃肿了一点。不过只要你理解了序列化的本质,无所谓用什么形式传输啦。
技术就是这样子,理解了可以随便玩。