java 序列化教程
序列化是将对象的状态信息转换为可存储或可传输的形式的过程,简而言之,把对象转换为字节数组的过程称之为对象的序列化。反序列化即序列化的逆过程。把字节数组恢复为对象的过程称为对象的反序列化。
序列化使用场景
- 通过将对象序列化为字节数组,使得不共享内存、通过网络连接的系统之间能够进行对象的传输。
- 通过将对象序列化为字节数组,能够将对象永久存储到存储设备。
- 解决远程接口调用 jvm 之间内存无法共享的问题。
评价序列化算法优劣的两个指标
- 序列化后码流的大小。
- 序列化本身的速度以及系统资源开销的大小(包括内存、cpu 等)。
java 序列化实现
先定义一个公共接口。
package com.xttblog.rpc.serialization.base;
// 业余草:www.xttblog.com
public interface MySerializer {
/**
* 序列化
* @param obj
* @param <T>
* @return
*/
<T> byte[] serialize(T obj);
/**
* 反序列化
* @param data
* @param clazz
* @param <T>
* @return
*/
<T> T deserialize(byte[] data, Class<T> clazz);
}
使用 java 原生的方式实现该接口。
package com.xttblog.rpc.serialization;
import com.xttblog.rpc.serialization.base.JavaSerializerModel;
import com.xttblog.rpc.serialization.base.JavaSerializerModel2;
import com.xttblog.rpc.serialization.base.MySerializer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class JavaSerialization implements MySerializer{
@Override
public <T> byte[] serialize(T obj) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(obj);
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toByteArray();
}
@Override
public <T> T deserialize(byte[] data, Class<T> clazz) {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
try {
ObjectInputStream objectInputStream= new ObjectInputStream(byteArrayInputStream);
return (T) objectInputStream.readObject();
} catch (Exception e) {
throw new RuntimeException();
}
}
public static void main(String[] args) {
JavaSerialization javaSerialization = new JavaSerialization();
JavaSerializerModel serializerModel = new JavaSerializerModel();
JavaSerializerModel model = javaSerialization.deserialize(javaSerialization.serialize(serializerModel), JavaSerializerModel.class);
System.out.println(model.getName());
System.out.println(model.getPhone());
System.out.println("------model2--------");
JavaSerializerModel2 serializerModel2 = new JavaSerializerModel2();
JavaSerializerModel2 model2 = javaSerialization.deserialize(javaSerialization.serialize(serializerModel2), JavaSerializerModel2.class);
System.out.println(model2.getName());
System.out.println(model2.getPhone());
}
}
java 的序列化主要是通过 OutputStream 与 InputStream 来实现的,被序列化的类需要实现 java.io.Serializable 接口。
上述的实现代码是使用 java 进行序列化与反序列化的通用代码。
关于 java 序列化的其他知识点
- 序列化时,只对对象的状态进行保存,而不管对象的方法。
- 当一个父类实现序列化时,子类自动实现序列化,不需要显示的实现 Serializable 接口。
- 当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化。
- 当某个字段被声明为 transient 后,默认的序列化机制会忽略该字段。
- 当某个字段被声明为 transient 后,如果想序列化该字段,需在类中添加 writeObject() 与 readObject() 方法。
序列化测试
JavaSerializerModel.java
package com.xttblog.rpc.serialization.base;
import java.io.Serializable;
public class JavaSerializerModel implements Serializable {
private transient String name = "业余草";
private String phone = "www.xttblog.com";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
JavaSerializerModel2.java
package com.xttblog.rpc.serialization.base;
import java.io.Serializable;
public class JavaSerializerModel implements Serializable {
private transient String name = "业余草";
private String phone = "www.xttblog.com";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
测试类 Main.java
public static void main(String[] args) {
JavaSerialization javaSerialization = new JavaSerialization();
JavaSerializerModel serializerModel = new JavaSerializerModel();
JavaSerializerModel model = javaSerialization.deserialize(
javaSerialization.serialize(serializerModel), JavaSerializerModel.class);
System.out.println(model.getName());
System.out.println(model.getPhone());
System.out.println("------model2--------");
JavaSerializerModel2 serializerModel2 = new JavaSerializerModel2();
JavaSerializerModel2 model2 = javaSerialization.deserialize(
javaSerialization.serialize(serializerModel2), JavaSerializerModel2.class);
System.out.println(model2.getName());
System.out.println(model2.getPhone());
}
测试结果:
null
www.xttblog.com
------model2--------
业余草
www.xttblog.com
可以看到,添加 writeObject() 与 readObject() 方法后,transient 字段也被正确序列化了。
本文由 创作,采用 知识共享署名4.0 国际许可协议进行许可。本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为: 2021/05/18 02:37