范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Java对象为啥要实现Serializable接口?

  最近这段时间一直在忙着编写Java业务代码,麻木地搬着Ctrl-C、Ctrl-V的砖,在不知道重复了多少次定义Java实体对象时"implements Serializable"的C/V大法后,脑海中突然冒出一个思维(A):问了自己一句"Java实体对象为什么一定要实现Serializable接口呢?",关于这个问题,脑海中的另一个思维(B)立马给出了回复"居然问这么幼稚和基础的问题,实现Serilizable接口是为了序列化啊!",思维(A):"哦,好吧!然而,然后呢?"
  此时思维(B)陷入了沉默,突然感觉自己有点浅薄了,好像写了这么多年Java还真是没有太关注过Serializable这个接口!为什么一定要实现Serializable接口?它的底层原理是什么?为什么一定要序列化,序列化又是什么?关于这些问题,不知道各位读者朋友有没有过类似的问题,如果有那么我们就在这篇文章中一起寻找答案吧!当然,如果你对这些问题都很清楚,也欢迎表达看法! Serializable接口概述
  Serializable是http://java.io包中定义的、用于实现Java类的序列化操作而提供的一个语义级别的接口。Serializable序列化接口没有任何方法或者字段,只是用于标识可序列化的语义。实现了Serializable接口的类可以被ObjectOutputStream转换为字节流,同时也可以通过ObjectInputStream再将其解析为对象。例如,我们可以将序列化对象写入文件后,再次从文件中读取它并反序列化成对象,也就是说,可以使用表示对象及其数据的类型信息和字节在内存中重新创建对象。
  而这一点对于面向对象的编程语言来说是非常重要的,因为无论什么编程语言,其底层涉及IO操作的部分还是由操作系统其帮其完成的,而底层IO操作都是以字节流的方式进行的,所以写操作都涉及将编程语言数据类型转换为字节流,而读操作则又涉及将字节流转化为编程语言类型的特定数据类型。而Java作为一门面向对象的编程语言,对象作为其主要数据的类型载体,为了完成对象数据的读写操作,也就需要一种方式来让JVM知道在进行IO操作时如何将对象数据转换为字节流,以及如何将字节流数据转换为特定的对象,而Serializable接口就承担了这样一个角色。
  下面我们可以通过例子来实现将序列化的对象存储到文件,然后再将其从文件中反序列化为对象,代码示例如下:
  先定义一个序列化对象User: public class User implements Serializable {      private static final long serialVersionUID = 1L;        private String userId;      private String userName;        public User(String userId, String userName) {          this.userId = userId;          this.userName = userName;      }  }
  然后我们编写测试类,来对该对象进行读写操作,我们先测试将该对象写入一个文件: public class SerializableTest {        /**       * 将User对象作为文本写入磁盘       */      public static void writeObj() {          User user = new User("1001", "Joe");          try {              ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("/Users/guanliyuan/user.txt"));              objectOutputStream.writeObject(user);              objectOutputStream.close();          } catch (IOException e) {              e.printStackTrace();          }      }        public static void main(String args[]) {          writeObj();      }  }
  运行上述代码,我们就将User对象及其携带的数据写入了文本user.txt中,我们可以看下user.txt中存储的数据此时是个什么格式: java.io.NotSerializableException: cn.wudimanong.serializable.User      at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)      at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)      at cn.wudimanong.serializable.SerializableTest.writeObj(SerializableTest.java:19)      at cn.wudimanong.serializable.SerializableTest.main(SerializableTest.java:27)
  我们看到对象数据以二进制文本的方式被持久化到了磁盘文件中。在进行反序列化测试之前,我们可以尝试下将User实现Serializable接口的代码部分去掉,看看此时写操作是否还能成功,结果如下:
  结果不出所料,果然是不可以的,抛出了NotSerializableException异常,提示非可序列化异常,也就是说没有实现Serializable接口的对象是无法通过IO操作持久化的。
  接下来,我们继续编写测试代码,尝试将之前持久化写入user.txt文件的对象数据再次转化为Java对象,代码如下: public class SerializableTest {      /**       * 将类从文本中提取并赋值给内存中的类       */      public static void readObj() {          try {              ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("/Users/guanliyuan/user.txt"));              try {                  Object object = objectInputStream.readObject();                  User user = (User) object;                  System.out.println(user);              } catch (ClassNotFoundException e) {                  e.printStackTrace();              }          } catch (IOException e) {              e.printStackTrace();          }      }          public static void main(String args[]) {          readObj();      }  }
  通过反序列化操作,可以再次将持久化的对象字节流数据通过IO转化为Java对象,结果如下: cn.wudimanong.serializable.User@6f496d9f
  此时,如果我们再次尝试将User实现Serializable接口的代码部分去掉,发现也无法再文本转换为序列化对象,报错信息为: java.io.InvalidClassException: cn.wudimanong.serializable.User; class invalid for deserialization      at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:157)      at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:862)      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2038)      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568)      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:428)      at cn.wudimanong.serializable.SerializableTest.readObj(SerializableTest.java:31)      at cn.wudimanong.serializable.SerializableTest.main(SerializableTest.java:44)
  提示非法类型转换异常,说明在Java中如何要实现对象的IO读写操作,都必须实现Serializable接口,否则代码就会报错! 序列化&反序列化
  通过上面的阐述和示例,相信大家对Serializable接口的作用是有了比较具体的体会了,接下来我们上层到理论层面,看下到底什么是序列化/反序列化。序列化是指把对象转换为字节序列的过程,我们称之为对象的序列化,就是把内存中的这些对象变成一连串的字节(bytes)描述的过程。
  而反序列化则相反,就是把持久化的字节文件数据恢复为对象的过程。那么什么情况下需要序列化呢?大概有这样两类比较常见的场景:1)、需要把内存中的对象状态数据保存到一个文件或者数据库中的时候,这个场景是比较常见的,例如我们利用mybatis框架编写持久层insert对象数据到数据库中时;2)、网络通信时需要用套接字在网络中传送对象时,如我们使用RPC协议进行网络通信时; 关于serialVersionUID
  对于JVM来说,要进行持久化的类必须要有一个标记,只有持有这个标记JVM才允许类创建的对象可以通过其IO系统转换为字节数据,从而实现持久化,而这个标记就是Serializable接口。而在反序列化的过程中则需要使用serialVersionUID来确定由那个类来加载这个对象,所以我们在实现Serializable接口的时候,一般还会要去尽量显示地定义serialVersionUID,如: private static final long serialVersionUID = 1L;
  在反序列化的过程中,如果接收方为对象加载了一个类,如果该对象的serialVersionUID与对应持久化时的类不同,那么反序列化的过程中将会导致InvalidClassException异常。例如,在之前反序列化的例子中,我们故意将User类的serialVersionUID改为2L,如: private static final long serialVersionUID = 2L;
  那么此时,在反序例化时就会导致异常,如下: java.io.InvalidClassException: cn.wudimanong.serializable.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2      at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687)      at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1880)      at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1746)      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2037)      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568)      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:428)      at cn.wudimanong.serializable.SerializableTest.readObj(SerializableTest.java:31)      at cn.wudimanong.serializable.SerializableTest.main(SerializableTest.java:44)
  如果我们在序列化中没有显示地声明serialVersionUID,则序列化运行时将会根据该类的各个方面计算该类默认的serialVersionUID值。但是,Java官方强烈建议所有要序列化的类都显示地声明serialVersionUID字段,因为如果高度依赖于JVM默认生成serialVersionUID,可能会导致其与编译器的实现细节耦合,这样可能会导致在反序列化的过程中发生意外的InvalidClassException异常。因此,为了保证跨不同Java编译器实现的serialVersionUID值的一致,实现Serializable接口的必须显示地声明serialVersionUID字段。
  此外serialVersionUID字段地声明要尽可能使用private关键字修饰,这是因为该字段的声明只适用于声明的类,该字段作为成员变量被子类继承是没有用处的!有个特殊的地方需要注意的是,数组类是不能显示地声明serialVersionUID的,因为它们始终具有默认计算的值,不过数组类反序列化过程中也是放弃了匹配serialVersionUID值的要求。
  https://zhuanlan.zhihu.com/p/66210653

美法院判决中兴通讯五年合规监察期结束不附加任何处罚来源新华社据美国得克萨斯州一家法院日前判决及中国中兴通讯股份有限公司公告,美国对中兴通讯的合规监察期于美国时间22日结束,且不附加任何处罚,美国此前派驻该公司的监察官任期也于同日结音响界的特斯拉一前言BLUESOUND是一家致力于完美实现无线数字高保真音频的公司,也许你对这个品牌名并不熟悉,但提到NADPSB,只要对音响产品稍有接触的朋友,就应该知道了。BLUESOUND银行春招近万岗位虚席以待金融科技人才成限量版资源据证券日报记者不完全统计,已有农业银行交通银行民生银行等超10家银行发布招聘公告。对金融科技人才的招揽仍然是各家银行招聘的重点领域。本报记者李冰见习记者张博我现在离职了,正值春招打优化拍摄功能三星发布两款中低端5G智能手机据韩联社网站报道,三星电子近日在线发布旗下中低端入门级新机GalaxyA535G版和GalaxyA335G版。GalaxyA系列采用5纳米制程芯片,增强人工智能算力,优化夜景拍摄模织密信息安全防护网由13个部门联合修订发布的网络安全审查办法(以下简称办法)日前开始施行,受到广泛关注。国家网信办有关负责人表示,对办法进行修订,主要目的是进一步保障网络安全和数据安全,维护国家安全今日上市祥明智能鹿山新材中国经济网北京3月25日讯今日,祥明智能(301226)鹿山新材(603051)2只新股上市。祥明智能(301226)祥明智能主要从事微特电机风机及智能化组件的研发生产与销售,为H2000元买不到好手机?这3款性价比十足,好用不贵不知道从什么时候开始,国产手机普遍出现了大涨价,以往两三千元就可以选择一款旗舰机,但如今一款旗舰机都要五六千元以上,甚至有些直接突破了万元,这是很多消费者无法承受的,但也无法否认旗厦大科研团队首次揭示细胞原位坏死小体组织结构特征来源台海网台海网3月24日讯据福建日报报道前方就是细胞膜城,但城下还有条河,怎么办?混合谱系激酶结构域(MLKL)分子正在着急,突然看到河上有拼成的木块。于是,它们四位以上一组,踩你手机上都有哪些非常神奇的软件?背着宝剑的观点谢谢邀请!最近每天都有推送app,现在汇总推荐给你们1。完事儿推荐理由一款美到窒息的日常管理应用,可以用来做日记做记录写待办事项设定目标建立养成习惯等。2。NFC卡模为什么苹果手机把后壳改成玻璃?苹果11以上的手机采用了无线充电技术,这个技术可以说在品牌机机型中苹果是最后一家采用。手机无线充电技术是日本夏普手机在2005年最先采用,苹果手机晚了整整10年。无线充电技术其实很超级小桀6万人砍不下1台手机,拼多多砍一刀的背后,有何猫腻?网友6万人能砍一座城,却砍不下资本家手里的一台手机终于有人揭露拼夕夕的砍一刀套路了。近日,游戏主播超级小桀借着高人气,在直播间让网友帮忙砍一刀,帮助自己在拼夕夕免费领手机活动中,拿
盘点苹果不值得购买的几款产品,买了的都是给库克清库存的提起Apple的产品你会想到哪些?是永恒的经典iPhone4?是引领了无线耳机的AirPods?又或是平板中的王者ipad?这些产品虽然都是一如既往的贵,但是又是那么无可替代,它们特斯拉推出售价16万的中低端车型,新车渲染图流出特斯拉作为新能源行业巨头,国内消费者对这个品牌的喜爱度也很高涨。最近,在特斯拉的全体员工大会上,特斯拉CEO马斯克表示计划在2023年推出售价2。5万美元(约16万人民币)的中低端苹果iPodClassic这一次可能真的要来了来自国外的设计师AndreaCopellino把iPodClassic又发布了。iPod一经推出就引起了轰动,真正让Apple从小众的电脑厂商成为一家巨型的科技公司。并且几乎一夜之打造智能生活体验!百度李彦宏人工智能带来科技新体验在日前召开的2021百度世界大会上,Robin表示AI,也是爱,是技术和温度结合在一起。让每一个人都感受到技术带来的改变,这就是技术的价值。人工智能技术的应用,已经开始重塑多个行业特斯拉制造人形机器人,预计明年上市日前,特斯拉已经正式宣布进军机器人领域,预计第一款特斯拉机器人将会在明年上市。特斯拉方面表示称,这款机器人的名字为TeslaBot,它将会替代人类去执行那些危险重复无聊的任务。同时世界机器人大会开幕一大波机智boys精彩亮相来源人民网原创稿人民网北京9月10日电(记者王震)会打太极的熊猫人会翻跟头的机器狗远程撸猫机器人今日,2021世界机器人大会在北京亦庄亦创国际会展中心开幕,在与大会同期举办的博览会联发科下一代旗舰处理器将采用台积电4nm制程ARMV9架构来自中国科技博客的消息指,台湾芯片生产商MediaTek(联发科)已经准备下一代旗舰级移动处理器Dimensity2000,有指他们向部分手机生产商提供了样本,让他们可以提早进行内又一批APP涉黄,无限期下架9月7日,新京报称,即日起,欢聚集团旗下的Hello语音虎牙旗下的小鹿陪玩鱼泡泡的比心咪呀可可西里一派陪玩比伴陪玩被无限期下架。经过测试,上述多款陪玩APP目前在各大手机应用市场已腾讯60岁退休老人凌晨五杀是本人!体验服资格已全部取消大家好,我是七七。在8月30日出版署发布了关于进一步严格管理,切实防止未成年人沉迷网络游戏的通知之后,腾讯表示坚决支持并且积极响应,立马做出了相应地措施,实施起了更加严格的未成年防为了实现共同富裕,阿里腾讯各出1000个亿共同富裕这个词对于很多人来说并不陌生,这个词语在经济学的领域之中更是多次出现。共同富裕这个词语更是中国特色社会主义理论中的重要内容之一。长久以来对于中国来说,社会主义的基本性质就是微信或将开始收费,最低130元一年,刚砸了1000亿的腾讯缺钱了?如果让你手机只留下一个APP,你会选择哪一个呢?我想大部分人会选择留下的就是微信,因为微信已经不只是一个聊天软件,在微信上,你可以购物支付看新闻看视频,微信的小程序也囊括了大多数的