java中的序列化和反序列化
一:序列化和反序列化的概念:
先来介绍下在java中序列化和反序列化的含义:
1、对象序列化:是指把对象(包括类对象,字符串等)序列化成字节序列。
2、把字节序列转化成对象。
二:序列化的应用:
1、对象持久化到硬盘:我们在java运行的过程中把想要持久化的对象存储在磁盘中或者我们在搭建服务器的时候为了提
高响应效率,在本地磁盘上存储用户的登陆信息(session),避免去数据库中读取筛选。我们需要把这些对象存储在本地磁
盘中。持久化对象。我们需要用到对象的序列化来达到这个效果。
2、对象序列化进行网络传输:在网络传输的过程中,都是以字节流的形式进行传输。我们如果传输字符串,就不需要就行
对象序列化了。但是我们入伙传输一个实体的对象,就需要对对象进行序列化。这样在传输完毕之后在进行反序列化得到
对象。
三:序列化和反序列化在java中的API:
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,
对象序列化包括如下步骤:
- 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
- 通过对象输出流的writeObject()方法写对象。
对象反序列化的步骤如下:
- 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
- 通过对象输入流的readObject()方法读取对象。
四:简单实现对象序列化在本地磁盘和读取磁盘文件反序列化成java对象。
person.java:
package MM;
import java.io.Serializable;
public class Person implements Serializable{
private static final long serialVersionUID = 5878272943999L;
private int age;
private String name;
private String sex;
public int getAge() {
return age;
}
public void setAge(int age) {
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 [age=" + age + ", name=" + name + ", sex=" + sex + "]";
}
}
test.java:
package MM;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class TestSerializable{
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
SerializePerson();
DeserializePerson();
}
public static boolean SerializePerson() throws FileNotFoundException, IOException {
boolean flag=true;
Person person=new Person();
person.setAge(18);
person.setName("lyc");
person.setSex("male");
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("E:/person.txt"));
out.writeObject(person);
System.out.println("对象序列化成功");
out.close();
return flag;
}
public static Person DeserializePerson() throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream in=new ObjectInputStream(new FileInputStream("E:/person.txt"));
Person person=(Person) in.readObject();
System.out.println(person.toString());
System.out.println("对象反序列化成功");
return null;
}
}
需要注意的是:这个txt用文本编辑器打开之后是乱码,无法查看。因为序列化和反序列化过程都是基于二进制流的形式进
行的,从一定角度来说可以对数据有保护作用。
五:对象序列化安全性问题:
在本地服务器上的序列化安全问题还比较好说。因为在你本地计算机上操作,别人无法干预。但是如果在网络上序列化
传输对象就需要对序列化的安全问题考虑了。
1、对象序列化和反序列化本身是基于二进制流的操作,但是你的网络请求被拦截之后,可以通过UltraEdit软件进行查看
修改之后再发给别人,或者反序列化,修改之后再序列化。所以不做任何加密是不安全的。
2、md5算法加密序列化对象。都说md5是不可以被破译的,你可以通过网络传输之间的约定来约定加密的字段的信息。
但是由于一些破译工具的强大,一些简单的MD5加密还是可以破译。
3、采用对称加非对称算法进行加密,网络传输的东西有一部分是真实的数据,一部分用MD5加密。一部分用AES加密。
另一部分是真正要传输的数据。这样破解难度就比较大了。可能黑客想要破解就要花费很长的时间。
六:序列化Id的作用:
序列化id就是当我们的类实现Serializable接口要序列化对象时,IDEA编译器提示我们要指定一个serialVersionUID
为什么需要我们显示指定这个private static final long serialVersionUID呢?
这个serialVersionUID的值是与序列化与反序列化能否正常成功有密切的关系,可以理解为当作这个类的版本号的作用。
当反序列化的时候的版本号(即这个serialVersionUID)的值与序列化的时候的值不一样会抛出异常,序列化对象失败。
注意:
当我们对这个类进行改变的时候,重新编译之后序列化id(serialVersionUID)是会变化的。
不同的编译器编译的时候产生的序列化id也是不同的。
所以指定一个序列化id是需要的,当然你可以根据你的业务场景更新这个序列化id。