什么是对象序列化和反序列化
序列化和反序列化是java中进行数据存储和数据传输的一种方式.
- 对象序列化:将对象转换为字节的过程。
- 对象反序列化:将字节转换为对象的过程。
注意:有时候把对象转换成字符串也可以理解为序列化 比如 对象转成json格式的字符串
序列化的应用场景
序列化和反序列化通常应用在:
- 网络通讯(C/S):以字节方式在网络中传输数据
- 数据存储(例如文件,缓存)
对象的序列化与反序列化实现
-
对象要实现serializable接口
-
添加序列化id(为反序列化提供保障)
-
借助对象流(ObjectOutPutStream和ObjectInPutStream)实现序列化和反序列化
package com.py;
import java.io.Serializable;
public class Message implements Serializable {
/**
*
*/
private static final long serialVersionUID = 5470084188709647684L;
private transient int id;
private String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Message [id=" + id + ", content=" + content + "]";
}
}
package com.py;
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 Exception {
Message msg=new Message();
msg.setId(100);
msg.setContent("你好");
ObjectOutputStream out=
new ObjectOutputStream(
new FileOutputStream("D:/f1.dat"));
//2.将对象序列化
out.writeObject(msg);
//3.释放资源
out.close();
System.out.println("序列化ok");
ObjectInputStream in=
new ObjectInputStream(
new FileInputStream("D:/f1.dat"));
Object obj=in.readObject();
in.close();
System.out.println(msg==obj);//false
System.out.println(msg.equals(obj));//false
System.out.println(obj);
}
}
- Seriazable接口只起一个标识性的作用.
- 建议实现序列化接口的类自动生成一个序列化id.假如没有在类中显式添加此id,不会影响对象的序列化,但可能会对反序列化有影响(对象结构发生变化).
- 系统底层会基于类的结构信息自动生成序列化id.
- 序列化和反序列化的顺序应该是一致的(先序列化谁,就先反序列化谁).
序列化的粒度如何控制?
所谓序列化粒度一般指对象序列化时,如何控制对象属性的序列化。例如哪些序列化,哪些属性不序列化。java中的具体方案一般有两种:
-
不需要序列化的属性使用Transient修饰.
当少量属性不需要序列化时,使用此关键字修饰比较方便.例如 private transient Integer id;(例如arraylist,hashmap中的属性) -
让序列化对象实现Externalizable接口,自己指定属性的序列化和反序列化过程, 但是要序列化的对象对应的类必须使用public修饰,一定要有默认的无参构造函数
package com.py;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* 在重写的方法中添加要序列化和反序列化的
* @author ASUS
*
*/
public class Message implements Externalizable {
private transient int id;
private String content;
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// TODO Auto-generated method stub
content=in.readUTF();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// TODO Auto-generated method stub
out.writeUTF(content);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Message [id=" + id + ", content=" + content + "]";
}
}
序列化的性能问题及如何优化
Java中默认的序列化机制,其性能相对较差。此性能的提升,目前会借助一些第三方的框架进行实现,例如kryo ,其官方API应用网址.
https://github.com/EsotericSoftware/kryo