目录
序列化的定义
序列化:把对象转化为可传输的字节序列过程称为序列化。
反序列化:把字节序列还原为对象的过程称为反序列化。
序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组。
在Java中如何将一个对象序列化呢?
最简单的把一个 String对象转化为字节流,再把字节流转化为一个String对象。
// string 转成 byte[]
public static byte[] stringToBytes(String str) {
// 只支持英文字符
if (str == null || str.length() == 0) {
// 如果字符串为 null 或者为空 都是空的byte数组
return new byte[0];
}
byte[] bytes = new byte[str.length()];
char[] chars = str.toCharArray();
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) chars[i];
}
return bytes;
}
public static String byteToString(byte[] bytes) {
if (bytes.length == 0) {
return null;
}
int len = bytes.length;
char[] charArray = new char[len];
for (int i = 0; i < bytes.length; i++) {
charArray[i] = (char) bytes[i];
}
return String.valueOf(charArray);
}
Java实现简单类的序列化(int 和 string字段的序列化)_trigger333的博客-CSDN博客
一个复杂对象如何进行序列化呢?
比如一个User对象,
public class User{
private Integer id;
private String username;
}
这时可以使用jdk自带的序列化框架 JDK Serializable,只需要实现Serializable接口,就可以进行序列化。
public class User implements Serializable {
private static final long serialVersionUID = 5342726393385586669L;
private Integer id;
private String username;
}
JDK Serializable中通过serialVersionUID
控制序列化类的版本,如果序列化与反序列化版本不一致,则会抛出java.io.InvalidClassException异常信息,提示序列化与反序列化SUID不一致。一般会手动指定SUID。
Java 序列化详解_Gerald Newton的博客-CSDN博客_java序列化详解
public class JdkSerializeFactory implements SerializeFactory {
@Override
public <T> byte[] serialize(T t) {
byte[] data = null;
try {
// 字节数组输出流在内存中创建一个字节数组缓冲区,所有发送
// 到输出流的数据保存在该字节数组缓冲区中。
// 创建字节数组输出流对象有以下几种方式。
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream output = new ObjectOutputStream(os);
output.writeObject(t);
//bugfix 解决readObject时候出现的eof异常
output.writeObject(null);
output.flush();
data = os.toByteArray();
// 关闭
output.close();
os.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
return data;
}
@Override
public <T> T deserialize(byte[] data, Class<T> clazz) {
ByteArrayInputStream is = new ByteArrayInputStream(data);
try {
ObjectInputStream input = new ObjectInputStream(is);
Object result = input.readObject();
return ((T) result);
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
缺点:
- 不支持跨语言调用 : 如果调用的是其他语言开发的服务的时候就不支持了。
- 性能差 :相比于其他序列化框架性能更低,主要原因是序列化之后的字节数组体积较大,导致传输成本加大,同时在序列化反序列化的时候耗时比较长。