序列化的意義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)調用訂單系統,底層傳輸的事二進制數據,那麼咱們要作的事情就是把對象轉化爲一個二進制數據,這就是序列化的場景。