序列化的意义java
常见的序列化工具git
Java自己自带的序列化github
@Override public <T> byte[] serializer(T obj) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = null; try { objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(obj); } catch (IOException e) { e.printStackTrace(); } finally { if(objectOutputStream != null) { try { objectOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return byteArrayIutputStream.toByteArray(); } @Override public <T> T deSerializer(byte[] bytes, Class<T> clazz) { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); ObjectInput objectInput = null; try { objectInput = new ObjectInputStream(byteArrayInputStream); return (T)objectInput.readObject(); } catch (Exception e) { e.printStackTrace(); } return null; }
对于一个但愿经过序列化的类,可能会报InvalidClassException,这是由于序列化的类最好加上serialVersionUID,用来让系统判断序列化的可靠性。算法
serialVersionUID 的做用
Java 的序列化机制是经过判断类的serialVersionUID 来验证版本一致性的。在进行反序列化时,JVM 会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID 进行比较,若是相同就认为是一致的,能够进行反序列化,不然就会出现序列化版本不一致的异常,便是InvalidCastException若是没有为指定的class 配置serialVersionUID,那么java 编译器会自动给这个class 进行一个摘要算法,相似于指纹算法,只要这个文件有任何改动,获得的UID 就会大相径庭的,能够保证在这么多类中,这个编号是惟一的。json
serialVersionUID 有两种显示的生成方式:
一是默认的1L,好比:private static final long serialVersionUID = 1L;
二是根据类名、接口名、成员方法及属性等来生成一个64 位的哈希字段。
当实现java.io.Serializable 接口的类没有显式地定义一个serialVersionUID 变量时候,Java 序列化机制会根据编译的Class 自动生成一个serialVersionUID 做序列化版本比较用,这种状况下,若是Class 文件(类名,方法明等)没有发生变化(增长空格,换行,增长注释等等),就算再编译屡次,serialVersionUID 也不会变化的。api
Java对象序列化过程当中,若是序列化获得的对象增长或者减小一个变量,并不会报错,仅仅是某个字段读取不到。对于一个静态变量的序列化,静态变量不会参与序列化。由于序列化保存的是一个对象的状态,而静态变量属于一个类的状态。数组
transient架构
transient修饰的字段表示不会在序列化过程被保存,他的值在反序列化以后还是类定义的值。也能够手动写到流里面,来绕过序列化框架
序列化与继承分布式
若是说一个子类实现了序列化,父类没有实现序列化,在子类被反序列化以后,是没法得到父类的值,即子类继承父类已经被定义的那个值是空的。
若是一个父类实现序列化,那么子类自动实现序列化,不用继承Serializable接口。
对于同一个对象写入流两次,流里的数据不会加倍,而是增长五个字节(增长新增引用和一些控制信息的空间),由于当流里存在同一个对象的时候,只是会增长一个引用。这算是个优势,节省了存储空间。
序列化实现克隆
Java对于每一个接口类都具备克隆能力,但只是浅克隆。浅克隆只是新建对象,对原对象的一些变量只是复制它的引用。我实例2 克隆实例1,当实例2改变某个值后,实例1也会改变。深克隆实现Serializable接口,把对象序列化流中,再从流里读出来,这个对象就不是原来的对象了,全部的变量的引用都会新建一个引用。
xml序列化框架
优势是可读性强,缺点是序列化以后的数据比较大。在技术要求比较高的时候,通常不会用到它。
代码实例:
public class XmlSerializer { XStream xStream = new XStream(new DomDriver()); public <T> String serializer(T obj) { return xStream.toXML(obj); } public <T> T deSerializer(String bytes, Class<T> clazz) { return (T)xStream.fromXML(bytes); } public static void main(String[] args) { XmlSerializer iSerializer = new XmlSerializer(); User user = new User(); String bytes = iSerializer.serializer(user); user.setName("jolivan"); System.out.println(new String(bytes)); User userNow = iSerializer.deSerializer(bytes,User.class); System.out.println(userNow.getName()); System.out.println(userNow.getAge()); } } ==============输出================== <serial.User> <name>Lushe</name> <age>23</age> </serial.User> Lushe 23
咱们能够看到,根据数据咱们就知道他是个什么类,里面有啥。可读性很是高。
JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相对于XML 来讲,JSON 的字节流更小,并且可读性也很是好。如今JSON数据格式在企业运用是最广泛的
JSON 序列化经常使用的开源工具备不少
1. Jackson (https://github.com/FasterXML/jackson)
2. 阿里开源的FastJson (https://github.com/alibaba/fastjon)
3. Google 的GSON (https://github.com/google/gson)
这几种json序列化工具中,Jackson 与fastjson 要比GSON 的性能要好,可是Jackson、GSON 的稳定性要比Fastjson 好。而fastjson的优点在于提供的api 很是容易使用。
用阿里的FastJson来示例一下:
public class FastjsonSerializeer implements ISerializer { @Override public <T> byte[] serializer(T obj) { return JSON.toJSONBytes(obj); } @Override public <T> T deSerializer(byte[] bytes, Class<T> clazz) { return (T)JSON.parseObject(bytes,clazz); } public static void main(String[] args) { ISerializer iSerializer = new FastjsonSerializeer(); User user = new User(); byte [] bytes = iSerializer.serializer(user); user.setName("jolivan"); System.out.println(new String(bytes)); User userNow = iSerializer.deSerializer(bytes,User.class); System.out.println(userNow.getName()); } }
===================输出=====================
{"age":"23","name":"Lushe"}
Lushe
hessian
dubbo里使用的就是它,但对它作了优化,又称为hessian2。
Protobuf
优点:(1)独立语言(能够基于不一样的语言)、独立平台(跨平台交互)(2)性能高,压缩性好;(3)解析性好
缺陷:实现起来很麻烦,学习成本大。
它有独立的编译器
序列化的实际应用举例
好比说咱们在一个分布式系统中,有一个订单模块和一个支付模块,订单模块基于一个协议(dubbo)调用订单系统,底层传输的事二进制数据,那么咱们要作的事情就是把对象转化为一个二进制数据,这就是序列化的场景。