serialio java_java.io.Serializable浅析
Java API中java.io.Serializable接口源码:
public interface Serializable {}
类通过实现java.io.Serializable接口可以启用其序列化功能。未实现次接口的类无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
Java的"对象序列化"能让你将一个实现了Serializable接口的对象转换成byte流,这样日后要用这个对象时候,你就能把这些byte数据恢复出来,并据此重新构建那个对象了。
要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream。这时,你就能用writeObject()方法把对象写入OutputStream了。
writeObject()方法负责写入特定类的对象的状态,以便相应的 readObject()方法可以还原它。通过调用 out.defaultWriteObject 可以调用保存 Object 的字段的默认机制。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。
读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用readObject()方法。不过这样读出来的,只是一个Object的reference,因此在用之前,还得先下传。readObject() 方法负责从流中读取并还原类字段。它可以调用 in.defaultReadObject 来调用默认机制,以还原对象的非静态和非瞬态字段。 defaultReadObject()方法使用流中的信息来分配流中通过当前对象中相应命名字段保存的对象的字段。这用于处理类发展后需要添加新字段的情形。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。
在序列化时,有几点要注意的:
1:当一个对象被序列化时,只保存对象的非静态成员变量(包括声明为private的变量),不能保存任何的成员方法和静态的成员变量。
2:如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被序列化。
3:如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。
1、序列化是干什么的?
简单说就是为了保存在内存中的各种对象的状态,并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存Object States,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
2、什么情况下需要序列化
a)当你想把的内存中的对象保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;
3、当对一个对象实现序列化时,究竟发生了什么?
在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如:
Foo myFoo = newFoo();
myFoo .setWidth(37);
myFoo.setHeight(70);
当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。
FileOutputStream fs = new FileOutputStream("foo.ser");
ObjectOutputStream os= newObjectOutputStream(fs);
os.writeObject(myFoo);
4、实现序列化(保存到一个文件)的步骤
a)Make a FileOutputStream
java 代码
FileOutputStream fs = new FileOutputStream("foo.ser");
b)Make a ObjectOutputStream
java 代码
ObjectOutputStream os = new ObjectOutputStream(fs);
c)write the object
java 代码
os.writeObject(myObject1);
os.writeObject(myObject2);
os.writeObject(myObject3);
d) close the ObjectOutputStream
java 代码
os.close();
5、举例说明
public class Box implementsSerializable {private static final long serialVersionUID = -3450064362986273896L;private intwidth;private intheight;public static voidmain(String[] args) {
Box myBox=newBox();
myBox.setWidth(50);
myBox.setHeight(30);try{
FileOutputStream fs=new FileOutputStream("F:\\foo.ser");
ObjectOutputStream os=newObjectOutputStream(fs);
os.writeObject(myBox);
os.close();
FileInputStream fi=new FileInputStream("F:\\foo.ser");
ObjectInputStream oi=newObjectInputStream(fi);
Box box=(Box)oi.readObject();
oi.close();
System.out.println(box.height+","+box.width);
}catch(Exception e) {
e.printStackTrace();
}
}public intgetWidth() {returnwidth;
}public void setWidth(intwidth) {this.width =width;
}public intgetHeight() {returnheight;
}public void setHeight(intheight) {this.height =height;
}
}
6、相关注意事项
a)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
b)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
c)并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如:
1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。
serialVersionUID
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java(TM) 对象序列化规范”中所述。不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值,原因是计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用 private 修饰符显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于直接声明类 -- serialVersionUID 字段作为继承成员没有用处。数组类不能声明一个明确的 serialVersionUID,因此它们总是具有默认的计算值,但是数组类没有匹配 serialVersionUID 值的要求。
serialio java_java.io.Serializable浅析相关推荐
- hadoop 023.0与hadoop 1.0 io.serializable分析
2019独角兽企业重金招聘Python工程师标准>>> hadoop升级到0.23.0和1.0版本后,其IO底层除了自己实现的Writable序列化后,还增加了一个io.serial ...
- java对象序列化java.io.Serializable 接口实践
java.io.Serializable 接口没有任何方法和字段,仅仅表示实现它的类的对象可以被序列化.实现了这个接口的所有类及其子类都可以对象序列化. 序列化前,虚拟机要清楚每个对象的结构,所以序列 ...
- java.io.Serializable 序列化问题【原】
java.io.Serializable 序列化问题 Person.java package a.b.c;public class Person implements java.io.Serializ ...
- 解决Serialized class ** must implement java.io.Serializable问题
在使用dubbo进行传递实体类时,会报错需要实现序列化问题 只需在自己的model实体类里面implements Serializable即可解决,如下 package com.pang.back.M ...
- 高性能IO模型浅析--范志东(Florian)
代码改变世界 Posts - 74, Articles - 4, Comments - 439 Cnblogs Dashboard Login Home Contact Gallery RSS Flo ...
- Serialized class com.xxx.xxxService must implement java.io.Serializable
大家好,我是烤鸭: 使用dubbo的时候,遇到如下的问题. Serialized class com.xxx.xxxService must implement java.io.Seriali ...
- dubbo 报错Serialized class com.spring.boot.entity.User must implement java.io.Serializable
这个报错是说dubbo在传输数据的时候反序列化报错, 使用dubbo进行数据传递时,需让作为消息传递的类序列化. 2019-03-26 16:45:01.228 ERROR 14968 --- [ni ...
- Dubbo Serialized class xxx.Xxx must implement java.io.Serializable问题解决
问题描述: Caused by: java.lang.IllegalStateException: Serialized class com.user.UserDto must implement j ...
- 错误记录——Serialized class com.cql.entity.Teacher must implement java.io.Serializable
在使用dubbo的时候,出现Serialized class com.*.xxx must implement java.io.Serializable,的一个错误 原因:实体类未进行序列化,在对应的 ...
最新文章
- 理解矩阵的掩码操作 使用opencv锐化图片
- 撩课-Java每天5道面试题第11天
- numpy——hsplit()、vsplit()函数的详细使用
- 剧情反转:今年AI要凉!薪资碾压全行,但人才缺500万!
- mysql大数据量使用limit分页,随着页码的增大,查询效率越低下。
- matlab空间球与空间圆求解,基于MATLAB的球管相贯空间曲线焊缝的数学模型
- IE调试网页之二:F12 开发人员工具入门 (Windows)
- php 小说采集系统,YGBOOK小说采集系统 php版 v1.4
- 光伏发电与计算机控制,独立太阳能光伏发电系统的控制设计与实现
- Ubuntu系统清理瘦身
- 信息课为什么不叫计算机课,让信息技术课“美”起来
- Latex——页眉页脚
- 华为日历怎么显示一月_华为手机日历怎么设置
- java9新特性-4-模块化系统: Jigsaw与Modularity
- (24) T-GCN-时间图卷积网络用于交通预测
- 通过 Hostapd 进行 WIFI 热点共享上网
- 关于在u-boot中使用usb进行通信(一)
- 新库上线 | CnOpenData·A股上市公司现场检查随机抽查数据
- 国标BAL 13-3铝白铜棒 BAL 13-3性能
- mysql更新多表sql语句怎么写_MySQL多表updatesql语句总结
热门文章
- Chrome浏览器任意修改网页内容
- linux SPI驱动代码追踪
- SpringBoot 基于RequestBodyAdvice 和 ResponseBodyAdvice 实现数据的加/解密(采用 RSA 算法 ),“船新版本”!
- 米联客 ZYNQ/SOC 精品教程 S02-CH19 利用BRAM进行PS与PL间数据交互
- 【Linux】零基础学习动静态库打包
- CNET盘点2012年IT人物:进退得意还是没落迷茫
- touchmove事件里对线条stroke执行clearRect失效
- Marquee 文字轮播的使用参数详解
- 2023版信息系统项目管理师考试大纲
- 记一次web漏洞挖掘随笔