电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

JAVA序列化Serializable及Externalizable區別詳解

瀏覽:3日期:2022-08-29 10:08:21

序列化簡介

Java 的對象序列化將那些實現 Serializable 接口的對象轉換成一個字節序列,并能在之后將這個字節序列完全恢復為原來的對象。這就意味著 Java 對象在網絡上的傳輸可以不依賴于當前計算機的操作系統,就可以將對象進行傳遞,這也是Java跨平臺的一種體現。

Java 對象的序列化主要支持兩種特性:

1、Java的遠程方法調用(Remote Method Invocation RMI);

2、對于 JavaBean 來說,序列化也是必須的。

要序列化一個對象,需要創建一個 OutputStream 對象,然后將其封裝在 ObjectOutputStream 對象中,再調用 writeObject() 方法就可以完成對象的序列化(也是在這一步進行序列化);反序列化(將一個序列還原為一個對象)就是該過程的反過程:創建一個 InputStream 對象,將其封裝在 ObjectInputStream 對象中,使用 readObject() 方法將序列反序列化為對象,當然這是一個Object類型的對象,需要向下轉型為我們需要的類型(如果該類型不在本地,會導致反序列化失敗,ClassNotFoundException )。

先說結論

序列化有以下方式:

1、實現 Serializable 接口:

2、實現 Externalizable 接口,并重寫 writeExternal() readExternal() 方法;

3、(即下文中的 Externalizable 的替代方式進行序列化)如果不想實現Externalizable 接口,又想按照自己的規則進行序列化,可以實現 Serializable 接口,并在該類中添加(添加,不是覆蓋、實現)名為 writeExternal() readExternal() 方法,且這兩個方法必須為下面這兩個準確的方法簽名:

private void writeObject(ObjectOutputStream stream) throws IOException;private void readObject(ObjectInputStream stream) throws IOException,ClassNotFoundException;

一、三種方式完成序列化

1、實現 Serializable 接口序列化

這種方式最為常用且常見,只需要對需要序列化的類實現 Serializable 即可,對于不希望進行序列化的,可以使用 transient 關鍵詞進行修飾(即瞬時變量)。這種方式序列化的特征:

1、 Serializable 接口僅僅是一個標記接口,不包含任何方法;

2、對于Serializable對象來說,對象完全以它存儲的二進制位為基礎來構造,(反序列化)不會調用構造器。

2、實現 Externalizable 接口序列化

這種方式可以實現序列化的完全自定義:所有成員變量是否序列化都需要在 writeExternal()、readExternal()方法中寫出;且可以完全自定義序列化方式(在 writerExternal()、readExternal()方法中)。當然,實現 Externalizable 接口必須要重寫這兩個方法。這種方式序列化的特征:

1、必須重寫 writerExternal()、readExternal()兩個方法,并在兩個方法中寫出所有需要序列化的成員變量;

2、對于 Externalizable對象來說,必須要有無參public構造器,不然會報出 InvalidClassException 異常。

3、 Externalizable 的替代方式進行序列化

讓 ObjectOutputStream 和 ObjectInputStream 對象的 writeObject() 方法和 readObject() 方法調用我們編寫的這兩個方法。如果想在這種方式中也調用原有默認提供的方式,可以在 writeObject() 中調用: s.defaultWriteObject();,在 readObject() 中調用 s.defaultReadObject();。 這部分代碼可以查看 ArrayList 源碼。

二、測試代碼

1、 Serializable 對象反序列化,不調用任何構造器

Serializable 對象反序列化不調用任何構造器,包括默認構造器,整個對象都是從 InputStream 中取得數據恢復過來的

主測試類 Dogs

public class Dogs { public static void main(String[] args) throws Exception { // 創建對象 System.out.println('--- 創建對象 ---'); Dog1 d1 = new Dog1('pidan',4.0); Dog2 d2 = new Dog2('duanwu','black'); // 序列化 System.out.println('--- 序列化 ---'); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream('D:/dogs.out')); oos.writeObject(d1); oos.writeObject(d2); System.out.println('--- 反序列化 ---'); // 反序列化 不會調用任何構造器 ObjectInputStream ois = new ObjectInputStream(new FileInputStream('d:/dogs.out')); Dog1 o1 = (Dog1) ois.readObject(); Dog2 o2 = (Dog2) ois.readObject(); System.out.println('反序列化 o1 : ' + o1); System.out.println('反序列化 o2 : ' + o2); }}

Serializable 對象 Dog1 Dog2 類

class Dog1 implements Serializable { private static final long serialVersionUID = -7101743601344663182L; private String name; private Double weight; public Dog1(String name, Double weight) { System.out.println('Dog1 構造器運行 ---'); this.name = name; this.weight = weight; System.out.println('Dog1 : ' + this); } // 省略get、set、toString方法}public class Dog2 implements Serializable { private static final long serialVersionUID = -5462607652670703938L; private String name; private String color; public Dog2(String name, String color) { System.out.println('Dog2 構造器運行 ---'); this.name = name; this.color = color; System.out.println('Dogs2 : ' + this); } // 省略get、set、toString方法}

運行結果:

--- 創建對象 ---Dog1 構造器運行 ---Dog1 : Dog1{name=’pidan’, weight=4.0}Dog2 構造器運行 ---Dogs2 : Dog2{name=’duanwu’, color=’black’}--- 序列化 ------ 反序列化 ---反序列化 o1 : Dog1{name=’pidan’, weight=4.0}反序列化 o2 : Dog2{name=’duanwu’, color=’black’}

再最后取出對象時,完全沒有調用到其任何構造器。

2、無參構造器對 Externalizable 對象序列化的影響

主測試代碼:

public class Persons { public static void main(String[] args) throws Exception { // 創建對象 System.out.println('Init Objects'); Person1 p1 = new Person1(); Person2 p2 = new Person2(); // 存儲在磁盤上 ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream('d:/person.out')); os.writeObject(p1); os.writeObject(p2); os.flush(); os.close(); // 取出 ObjectInputStream is = new ObjectInputStream(new FileInputStream('d:/person.out')); System.out.println('取出p1: '); p1 = (Person1) is.readObject(); p2 = (Person2) is.readObject(); }}

Externalizable 對象:Perion1 Persion2

public class Person1 implements Externalizable { public Person1(){ System.out.println('Person1 構造器---'); } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println('Person1 writeExternal ---'); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println('Person1 readExternal ---'); }}class Person2 implements Externalizable{ // 注意不是public Person2(){ System.out.println('Person2 構造器 ---'); } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println('Person2 writeExternal ---'); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println('Person2 readExternal ---'); }}

Person2 默認構造器不是 public 的運行結果:

Init ObjectsPerson1 構造器---Person2 構造器 ---Person1 writeExternal ---Person2 writeExternal ---取出p1: Person1 構造器---Person1 readExternal ---Exception in thread 'main' java.io.InvalidClassException: ...serializableAndexternalizable.Person2; no valid constructorat java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:169)at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:874)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2043)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)at ...serializableAndexternalizable.Persons.main(Persons.java:29)Process finished with exit code 1

將 Person2 構造器改為 public 后:

Init ObjectsPerson1 構造器---Person2 構造器 ---Person1 writeExternal ---Person2 writeExternal ---取出p1: Person1 構造器---Person1 readExternal ---Person2 構造器 ---Person2 readExternal ---

3、使用 Externalizable 對象實現序列化

主測試類 Cats :

public class Cats { public static void main(String[] args) throws Exception { // 初始化對象 System.out.println('--- 初始化對象 ---'); Person person = new Person('01', '老王', 30); Cat2 cat = new Cat2('fugui', person); // 序列化 System.out.println('--- 序列化對象 ---'); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream('d:/cats.out')); oos.writeObject(cat); System.out.println('--- 反序列化對象 ---'); ObjectInputStream ois = new ObjectInputStream(new FileInputStream('d:/cats.out')); cat = (Cat2) ois.readObject(); System.out.println('--- 反序列化對象后 ---'); System.out.println('cat : ' + cat); }}

Externalizable 對象: Cat2 ;Serializable 對象:Person :

public class Person implements Serializable { private static final long serialVersionUID = -822166081906894628L; private transient String id; private String name; private int age; public Person() { System.out.println('--- Person 無參構造器 ---'); } public Person(String id, String name, int age) { System.out.println('--- Person 無參構造器 ---'); this.id = id; this.name = name; this.age = age; System.out.println('Person : ' + this); } // 省略get、set、toString方法}class Cat2 implements Externalizable { private static final long serialVersionUID = 1102930161606017855L; private String name; private Person minion; public Cat2() { System.out.println('Cat2 無參構造器 --->'); } public Cat2(String name, Person minion) { System.out.println('Cat2 有參構造器 --->'); this.name = name; this.minion = minion; System.out.println('Cat2 : ' + this); } // 省略get、set、toString方法 @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println('--- Cat2:writeExternal ---'); // code1 out.writeObject(this.minion); out.writeObject(this.name); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println('--- Cat2:readExternal ---'); // code2 this.minion = (Person) in.readObject(); this.name = (String) in.readObject(); }}

運行結果:

可以注意到Person的成員變量id在使用了 transient 關鍵詞修飾后,就不再序列化該字段了。

--- 初始化對象 ------ Person 無參構造器 ---Person : Person{id=’01’, name=’老王’, age=30}Cat2 有參構造器 --->Cat2 : Cat2{name=’fugui’, minion=Person{id=’01’, name=’老王’, age=30}}--- 序列化對象 ------ Cat2:writeExternal ------ 反序列化對象 ---Cat2 無參構造器 --->--- Cat2:readExternal ------ 反序列化對象后 ---cat : Cat2{name=’fugui’, minion=Person{id=’null’, name=’老王’, age=30}}

如果將Cat2類中標注的 code1 與 code2 代碼下面的兩行代碼均注釋掉,就不再可以序列化及反序列化了:注釋掉后的運行結果:

--- 初始化對象 ------ Person 無參構造器 ---Person : Person{id=’01’, name=’老王’, age=30}Cat2 有參構造器 --->Cat2 : Cat2{name=’fugui’, minion=Person{id=’01’, name=’老王’, age=30}}--- 序列化對象 ------ Cat2:writeExternal ------ 反序列化對象 ---Cat2 無參構造器 --->--- Cat2:readExternal ------ 反序列化對象后 ---cat : Cat2{name=’null’, minion=null}

4、使用 Externalizable 對象替代方式實現序列化

替代方式就是實現 Serializable 接口,并且添加 writeObject(),readObject() 兩個方法注意這兩個方法必須有準確的方法特征簽名,在這兩個方法中編寫自定義方式實現序列化和反序列化。

class Mouse implements Serializable { private static final long serialVersionUID = -3278535893876444138L; private String name; private int i; public Mouse() { System.out.println('Mouse 無參構造器 ---'); } public Mouse(String name, int i) { System.out.println('Mouse 有參構造器 ---'); this.name = name; this.i = i; System.out.println('Mouse : ' + this); } // 方法特征簽名必須完全一致 private void writeObject(ObjectOutputStream stream) throws IOException {// stream.defaultWriteObject();// 可以選擇執行默認的writeObject() System.out.println('--- 這是自定義的writeExternal方法 ---'); stream.writeObject(this.name); stream.writeInt(this.i); } // 方法特征簽名必須完全一致 private void readObject(ObjectInputStream stream) throws IOException,ClassNotFoundException {// stream.defaultReadObject(); // 可以選擇執行默認的readObject() System.out.println('--- 這是自定義的readExternal方法 ---'); this.name = (String)stream.readObject(); this.i = stream.readInt(); } // 省略get、set、toString方法}

主測試類:

public class Mouses { public static void main(String[] args) throws Exception { // 創建對象 System.out.println('--- 創建對象 ---'); Mouse m1 = new Mouse('zhizhi', 2); // 序列化 System.out.println('--- 序列化 ---'); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream('D:/mouse.out')); oos.writeObject(m1); // 反序列化 System.out.println('--- 反序列化 ---'); ObjectInputStream ois = new ObjectInputStream(new FileInputStream('d:/mouse.out')); // 反序列化結果 System.out.println('--- 反序列化結果 ---'); m1 = (Mouse) ois.readObject(); System.out.println(' zhizhi : ' + m1); }}

運行結果

--- 創建對象 ---Mouse 有參構造器 ---Mouse : Mouse{name=’zhizhi’, i=2}--- 序列化 ------ 這是自定義的writeExternal方法 ------ 反序列化 ------ 反序列化結果 ------ 這是自定義的readExternal方法 ---zhizhi : Mouse{name=’zhizhi’, i=2}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Java
相關文章:
主站蜘蛛池模板: 安徽净化工程设计_无尘净化车间工程_合肥净化实验室_安徽创世环境科技有限公司 | 酒瓶_酒杯_玻璃瓶生产厂家_徐州明政玻璃制品有限公司 | 营养师网,营养师考试时间,报名入口—网站首页 | 飞利浦LED体育场灯具-吸顶式油站灯-飞利浦LED罩棚灯-佛山嘉耀照明有限公司 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | 氢氧化钙设备, 氢氧化钙生产线-淄博惠琛工贸有限公司 | 细沙回收机-尾矿干排脱水筛设备-泥石分离机-建筑垃圾分拣机厂家-青州冠诚重工机械有限公司 | 废气处理设备-工业除尘器-RTO-RCO-蓄热式焚烧炉厂家-江苏天达环保设备有限公司 | 拉力机-万能试验机-材料拉伸试验机-电子拉力机-拉力试验机厂家-冲击试验机-苏州皖仪实验仪器有限公司 | KBX-220倾斜开关|KBW-220P/L跑偏开关|拉绳开关|DHJY-I隔爆打滑开关|溜槽堵塞开关|欠速开关|声光报警器-山东卓信有限公司 | 英国公司注册-新加坡公司注册-香港公司开户-离岸公司账户-杭州商标注册-杭州优创企业 | 防锈油-助焊剂-光学玻璃清洗剂-贝塔防锈油生产厂家 | 广州云仓代发-昊哥云仓专业电商仓储托管外包代发货服务 | 5nd音乐网|最新流行歌曲|MP3歌曲免费下载|好听的歌|音乐下载 免费听mp3音乐 | 安徽成考网-安徽成人高考网| 合肥钣金加工-安徽激光切割加工-机箱机柜加工厂家-合肥通快 | 四探针电阻率测试仪-振实密度仪-粉末流动性测定仪-宁波瑞柯微智能 | 济南玻璃安装_济南玻璃门_济南感应门_济南玻璃隔断_济南玻璃门维修_济南镜片安装_济南肯德基门_济南高隔间-济南凯轩鹏宇玻璃有限公司 | 烽火安全网_加密软件、神盾软件官网 | 威客电竞(vk·game)·电子竞技赛事官网 | 浇注料-高铝砖耐火砖-郑州凯瑞得窑炉耐火材料有限公司 | 软瓷_柔性面砖_软瓷砖_柔性石材_MCM软瓷厂家_湖北博悦佳软瓷 | 深圳昂为官网-气体分析仪,沼气分析仪,动态配气仪,气体传感器厂家 | 智能垃圾箱|垃圾房|垃圾分类亭|垃圾分类箱专业生产厂家定做-宿迁市传宇环保设备有限公司 | 安徽成考网-安徽成人高考网| 工作服定制,工作服定做,工作服厂家-卡珀职业服装(苏州)有限公司 | 口信网(kousing.com) - 行业资讯_行业展会_行业培训_行业资料 | Q361F全焊接球阀,200X减压稳压阀,ZJHP气动单座调节阀-上海戎钛 | 电动葫芦|手拉葫芦|环链电动葫芦|微型电动葫芦-北京市凌鹰起重机械有限公司 | 全自动实验室洗瓶机,移液管|培养皿|进样瓶清洗机,清洗剂-广州摩特伟希尔机械设备有限责任公司 | 铝扣板-铝方通-铝格栅-铝条扣板-铝单板幕墙-佳得利吊顶天花厂家 elisa试剂盒价格-酶联免疫试剂盒-猪elisa试剂盒-上海恒远生物科技有限公司 | 100_150_200_250_300_350_400公斤压力空气压缩机-舰艇航天配套厂家 | 二手Sciex液质联用仪-岛津气质联用仪-二手安捷伦气质联用仪-上海隐智科学仪器有限公司 | 【星耀裂变】_企微SCRM_任务宝_视频号分销裂变_企业微信裂变增长_私域流量_裂变营销 | 便携式表面粗糙度仪-彩屏硬度计-分体式粗糙度仪-北京凯达科仪科技有限公司 | 地图标注|微信高德百度地图标注|地图标记-做地图[ZuoMap.com] | 中央空调维修、中央空调保养、螺杆压缩机维修-苏州东菱空调 | 粘度计维修,在线粘度计,二手博勒飞粘度计维修|收购-天津市祥睿科技有限公司 | 首页|光催化反应器_平行反应仪_光化学反应仪-北京普林塞斯科技有限公司 | 自动螺旋上料机厂家价格-斗式提升机定制-螺杆绞龙输送机-杰凯上料机 | 塑料瓶罐_食品塑料瓶_保健品塑料瓶_调味品塑料瓶–东莞市富慷塑料制品有限公司 |