Java序列化
是指把Java对象转换为字节序列的过程;而
Java反序列化
是指把字节序列恢复为Java对象的过程。
2.为什么需要序列化与反序列化
我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。
Java序列化的好处。其好处一是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列。
下面是序列化和反序列化的代码:
import java.io.BufferedWriter;
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 com.pojo.Model;
public class T4 {
public static void main(String[] args) {
T4 t = new T4();
try {
t.xuliehua();
t.fanxuliehua();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private void xuliehua() throws IOException{
Model model = new Model("123", 1, "1234");
model.setAddress("江西吉安");
FileOutputStream fs = new FileOutputStream(new File("E:\\123.txt"));
ObjectOutputStream ooStream = new ObjectOutputStream(fs);
ooStream.writeObject(model);
ooStream.flush();
ooStream.close();
fs.close();
}
private void fanxuliehua() throws IOException, ClassNotFoundException{
FileInputStream fs = new FileInputStream("E:\\123.txt");
ObjectInputStream os = new ObjectInputStream(fs);
Model model = (Model)os.readObject();
System.out.println(model.getName());
System.out.println(model.getAge());
System.out.println(model.getPhone());
System.out.println(model.getAddress());
}
}
import java.io.Serializable;
public class Model implements Serializable {
private String name;
private int age;
static String address = "江西";
private transient String phone;
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 static String getAddress() {
return address;
}
public static void setAddress(String address) {
Model.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Model(String name, int age, String phone) {
this.name = name;
this.age = age;
this.phone = phone;
}
}
运行结果:
123
1
null
江西吉安
为什么getPhone是null值?
因为在实体类中phone使用了transient关键字修饰符
另外
静态成员属于类级别的,所以不能序列化
这里的不能序列化的意思,是序列化信息中不包含这个静态成员域
上面测试成功,是因为都在同一个机器(而且是同一个进程),因为你这个jvm已经把address加载进来了,所以你获取的是加载好的address,如果你是传到另一台机器或者你关掉程序重写写个程序读入txt,此时因为别的机器或新的进程是重新加载
address
的,所以
address
信息就是初始时的信息(江西)。
在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。