基本概念Java中创建对象时,一旦程序终止,创建的对象可能就不存在.要想使得对象能够在程序不运行的状态下依然能够保存对象的信息,这时就需要用到序列化机制序列化机制:对象的数据对象的类型信息存储在对象中的数据类型一个对象可以被表示为一个字节序列,包括:将可序列化对象写入文件后,可以从文件中读取出来,根据对象的各种信息在内存中创建该对象.这里的读取并创建对象的过程就是反序列化序列化和反序列化的整个过程都是JVM独立的.也就是说,在一个JVM中的序列化对象可以在另一个完全不同的JVM中反序列化对象一般情况下,序列化需要实现java.io.Serializable接口,使用ObjectInputStream和ObjectOutputStream进行对象的读写操作还可以实现java.io.Externalizable接口,进行标准的序列化或者自定义的二进制格式.用来满足不同场景下的需求Java序列化场景:将Java对象的字节序列持久化到硬盘中在网络上传输对象的字节序列进行远程方法调用RMI(RemoteMethodInvocation)JVM运行结束时,还需要使用创建的对象需要将创建的对象保存下来以便后续的传输使得旧JVM创建的对象能够在一个新的JVM中运行Java序列化注意点:对象的序列化保存的是对象成员变量对象,对象的序列化不会关注类中的静态变量类的序列化要保证类的所有属性都是可以序列化的,如果想要某个属性不被序列化.可以声明为瞬时态transient序列化Java对象序列化:使得可序列化的对象实现Serializable接口创建一个ObjectOutputStream输出流调用ObjectOutputStream对象的writeObject()方法进行输出可序列化对象即可序列化示例:反序列化Java对象反序列化:创建一个ObjectInputStream输入流调用ObjectInputStream对象的readObject()方法得到序列化对象反序列化的对象是由JVM生成的对象,而不是通过类的构造函数生成的:反序列化对象时,JVM中要存在对象对应的类,否则会抛出ClassNotFoundException异常如果一个可序列化的类的成员不是基本类型,而是一个引用类型时,那么这个引用类型必须实现Serializable接口,否则会抛出NotSerializableException异常序列化和反序列化总结实现Serializable接口就可以进行序列化的原因:保存到磁盘的对象都有一个序列化编号,当程序试图进行序列化时,会检查该对象是否已经序列化只有对象从未被序列化过时,才会将此对象序列化为字节序列,如果对象已经序列化过,那么直接输出序列化编号Java序列化机制不会重复序列化同一个对象,会记录已经序列化对象的编号,此时如果序列化了一个可变对象后,如果更改了对象的内容会再次进行序列化.如果没有更改内容,则不会将此对象转换为字节序列,只会保存序列化编号首先会处理之前被编写的以及不可替换的对象如果有的对象被替换了,则检查被替换的对象最后如果对象都被替换了,则进行原始的检查原始的检查即检查被替换的对象类型是否为String类型,数组类型,Enum类型或者实现了Serializable接口,符合条件就可以对检查的对象执行相应的序列化操作,否则将会抛出NotSerializableException异常writeObject():对于序列化的机制来说,如果对同一个对象执行多次序列化操作时,不会得到多个对象实现Serializable接口时可以重写writeObject()方法和readObject()方法:重写writeObject()方法和readObject()方法后,对象进行序列化和反序列化时,就会自动调用重写的writeObject()方法和readObject()方法实现Externalizable接口时可以重写writeExternal()方法和readExternal()方法:重写writeExternal()方法和readExternal()方法后,对象进行序列化和反序列化时,就会自动调用重写的writeExternal()方法和readExternal()方法自定义序列化策略Externalizable如果需要使得对象的一部分可以被序列化,另一部分数据不被序列化,此时可以自定义实现Externalizable接口,并且实现writeExternal()和readExternal()方法,可以在序列化和反序列化过程中自动调用来执行一些特殊的操作注意点:Serializable接口实现的对象是与二进制的构建有关的,不会调用构造器Externalizable接口实现的对象的所有构造函数都会被调用,所以要编写出类的无参和有参构造函数使用Externalizable自定义序列化示例:使用Externalizable自定义序列化时,为了保证序列化和反序列化的正确性,需要在writeExternal()方法中将信息写入,并且在readExternal()方法中恢复数据transient可以使用transient关键字配置一些重要的信息比如密码等不进行序列化transient关键字修饰的属性不会参与到序列化过程中transient关键字修饰的属性在反序列化过程中,如果是引用数据类型,则返回null.如果是基本数据类型,则返回默认值.不一定是基本数据类型序列化之前的值因为实现Externalizable接口的对象默认情况下不会保存任何字段,所以transient关键字只能和Serializable对象一起使用transient关键字的使用场景:服务器端给客户端发送序列化对象数据时,对象中存在敏感数据比如密码字符串,在序列化时进行加密,客户端拥有解密的密钥,只有在客户端进行反序列化时,才会对密码进行读取这时就可以对密码字符串对象使用transient修饰,这样可以一定程度上保证序列化对象的数据安全静态变量序列化时不会序列化静态变量静态变量属于类的状态,序列化中保存的是对象,也就是类的实例的状态序列化操作的是序列化中对象,也就是类的实例的状态,静态变量属于类的状态.所以序列化时不会对静态变量进行序列化序列化IDJava虚拟机进行反序列化:两个类的类路径和功能代码一致两个类的序列化ID,也就是serialVersionUID一致功能代码一致:客户端A将类对象序列化客户端B,客户端B进行反序列化这时要求A和B都有这样的一个类文件,功能代码一致,并且都实现了Serializable接口序列化的类和反序列化的类所实现的功能和功能相关的代码是一样的示例:serialVersionUID的两种生成方式:默认值1L通过类名,接口名和方法名以及属性随机生成的一个不重复的long类型的值在序列化ID,即serialVersionUID相同的情况下,即使序列化对象的序列化属性修改,序列化对象也可以进行反序列化.因此如果只是修改了方法或者修改了静态变量或transient变量,只要不修改序列化ID,那么反序列化就不会受到影响显式声明序列化ID,即serialVersionUID的场景:如果需要类的不同版本对序列化兼容,要确保类的不同版本具有相同的serialVersionUID如果不需要类的不同版本对序列化兼容,要确保类的不同版本具有不同的serialVersionUID序列化一个类的实例后,如果修改一个字段或者增加一个字段,如果没有设置类的serialVersionUID,就会导致无法反序列化旧的实例,会在反序列化时抛出异常序列化类添加SerialVersionUID后,如果修改一个字段或者增加一个字段,反序列化旧的实例时,修改的或者增加的字段的值会设置为初始化的值破坏单例除了反射可以破坏单例模式外,序列化和反序列化后会得到一个新的对象,也可以破坏单例模式序列化和反序列化破坏单例模式:反序列化时,使用ObjectInputStream对象中的readObject()方法readObject()的方法中调用readObject0()方法readObject0()方法中会返回一个checkResolve(readOrdinaryObject(unshared))readOrdinaryObject()方法用于读取并返回普通对象.这里的普通对象不包括String,Class,ObjectStreamClass,数组或者枚举常量这些对象isInstantiable()方法表示如果一个实现了Serializable接口或者Externalizable接口的类可以在运行时实例化,那么该方法就返回true如果可以在运行时序列化,就会调用desc.newInstance()方法使用反射的方式调用无参构造方法新建一个对象,创建一个类的新的实例如果类实现的是Serializable接口,就调用第一个不可进行序列化超类的无参构造方法数创建新的实例如果类实现的Externalizable接口,就调用公共的无参构造方法创建新的实例isInstantiable()方法表示如果一个实现了Serializable接口或者Externalizable接口的类可以在运行时实例化,那么该方法就返回true如果可以在运行时序列化,就会调用desc.newInstance()方法使用反射的方式调用无参构造方法新建一个对象,创建一个类的新的实例readOrdinaryObject()方法用于读取并返回普通对象.这里的普通对象不包括String,Class,ObjectStreamClass,数组或者枚举常量这些对象readObject0()方法中会返回一个checkResolve(readOrdinaryObject(unshared))反序列化时,使用ObjectInputStream对象中的readObject()方法readObject()的方法中调用readObject0()方法因为序列化过程中会通过反射调用无参构造函数创建一个新的对象,所以序列化会破坏单例模式为了防止序列化破坏单例模式,可以在Singleton.java中添加readResolve()方法并且指定要返回的对象的生成策略因为readOrdinaryObject()方法源码中的hasResolveMethod()表示如果实现了Serializable或者Externalizable接口的类中包含readResolve()方法就返回trueinvokeReadResolve()方法会通过反射的方式调用要被反序列化的类的readResolve()方法作者:攻城狮Chova链接:
基本概念Java中创建对象时,一旦程序终止,创建的对象可能就不存在.要想使得对象能够在程序不运行的状态下依然能够保存对象的信息,这时就需要用到序列化机制序列化机制:对象的数据对象的类型信息存储在对象中的数据类型一个对象可以被表示为一个字节序列,包括:将可序列化对象写入文件后,可以从文件中读取出来,根据对象的各种信息在内存中创建该对象.这里的读取并创建对象的过程就是反序列化序列化和反序列化的整个过程都是JVM独立的.也就是说,在一个JVM中的序列化对象可以在另一个完全不同的JVM中反序列化对象一般情况下,序列化需要实现java.io.Serializable接口,使用ObjectInputStream和ObjectOutputStream进行对象的读写操作还可以实现java.io.Externalizable接口,进行标准的序列化或者自定义的二进制格式.用来满足不同场景下的需求Java序列化场景:将Java对象的字节序列持久化到硬盘中在网络上传输对象的字节序列进行远程方法调用RMI(RemoteMethodInvocation)JVM运行结束时,还需要使用创建的对象需要将创建的对象保存下来以便后续的传输使得旧JVM创建的对象能够在一个新的JVM中运行Java序列化注意点:对象的序列化保存的是对象成员变量对象,对象的序列化不会关注类中的静态变量类的序列化要保证类的所有属性都是可以序列化的,如果想要某个属性不被序列化.可以声明为瞬时态transient序列化Java对象序列化:使得可序列化的对象实现Serializable接口创建一个ObjectOutputStream输出流调用ObjectOutputStream对象的writeObject()方法进行输出可序列化对象即可序列化示例:反序列化Java对象反序列化:创建一个ObjectInputStream输入流调用ObjectInputStream对象的readObject()方法得到序列化对象反序列化的对象是由JVM生成的对象,而不是通过类的构造函数生成的:反序列化对象时,JVM中要存在对象对应的类,否则会抛出ClassNotFoundException异常如果一个可序列化的类的成员不是基本类型,而是一个引用类型时,那么这个引用类型必须实现Serializable接口,否则会抛出NotSerializableException异常序列化和反序列化总结实现Serializable接口就可以进行序列化的原因:保存到磁盘的对象都有一个序列化编号,当程序试图进行序列化时,会检查该对象是否已经序列化只有对象从未被序列化过时,才会将此对象序列化为字节序列,如果对象已经序列化过,那么直接输出序列化编号Java序列化机制不会重复序列化同一个对象,会记录已经序列化对象的编号,此时如果序列化了一个可变对象后,如果更改了对象的内容会再次进行序列化.如果没有更改内容,则不会将此对象转换为字节序列,只会保存序列化编号首先会处理之前被编写的以及不可替换的对象如果有的对象被替换了,则检查被替换的对象最后如果对象都被替换了,则进行原始的检查原始的检查即检查被替换的对象类型是否为String类型,数组类型,Enum类型或者实现了Serializable接口,符合条件就可以对检查的对象执行相应的序列化操作,否则将会抛出NotSerializableException异常writeObject():对于序列化的机制来说,如果对同一个对象执行多次序列化操作时,不会得到多个对象实现Serializable接口时可以重写writeObject()方法和readObject()方法:重写writeObject()方法和readObject()方法后,对象进行序列化和反序列化时,就会自动调用重写的writeObject()方法和readObject()方法实现Externalizable接口时可以重写writeExternal()方法和readExternal()方法:重写writeExternal()方法和readExternal()方法后,对象进行序列化和反序列化时,就会自动调用重写的writeExternal()方法和readExternal()方法自定义序列化策略Externalizable如果需要使得对象的一部分可以被序列化,另一部分数据不被序列化,此时可以自定义实现Externalizable接口,并且实现writeExternal()和readExternal()方法,可以在序列化和反序列化过程中自动调用来执行一些特殊的操作注意点:Serializable接口实现的对象是与二进制的构建有关的,不会调用构造器Externalizable接口实现的对象的所有构造函数都会被调用,所以要编写出类的无参和有参构造函数使用Externalizable自定义序列化示例:使用Externalizable自定义序列化时,为了保证序列化和反序列化的正确性,需要在writeExternal()方法中将信息写入,并且在readExternal()方法中恢复数据transient可以使用transient关键字配置一些重要的信息比如密码等不进行序列化transient关键字修饰的属性不会参与到序列化过程中transient关键字修饰的属性在反序列化过程中,如果是引用数据类型,则返回null.如果是基本数据类型,则返回默认值.不一定是基本数据类型序列化之前的值因为实现Externalizable接口的对象默认情况下不会保存任何字段,所以transient关键字只能和Serializable对象一起使用transient关键字的使用场景:服务器端给客户端发送序列化对象数据时,对象中存在敏感数据比如密码字符串,在序列化时进行加密,客户端拥有解密的密钥,只有在客户端进行反序列化时,才会对密码进行读取这时就可以对密码字符串对象使用transient修饰,这样可以一定程度上保证序列化对象的数据安全静态变量序列化时不会序列化静态变量静态变量属于类的状态,序列化中保存的是对象,也就是类的实例的状态序列化操作的是序列化中对象,也就是类的实例的状态,静态变量属于类的状态.所以序列化时不会对静态变量进行序列化序列化IDJava虚拟机进行反序列化:两个类的类路径和功能代码一致两个类的序列化ID,也就是serialVersionUID一致功能代码一致:客户端A将类对象序列化客户端B,客户端B进行反序列化这时要求A和B都有这样的一个类文件,功能代码一致,并且都实现了Serializable接口序列化的类和反序列化的类所实现的功能和功能相关的代码是一样的示例:serialVersionUID的两种生成方式:默认值1L通过类名,接口名和方法名以及属性随机生成的一个不重复的long类型的值在序列化ID,即serialVersionUID相同的情况下,即使序列化对象的序列化属性修改,序列化对象也可以进行反序列化.因此如果只是修改了方法或者修改了静态变量或transient变量,只要不修改序列化ID,那么反序列化就不会受到影响显式声明序列化ID,即serialVersionUID的场景:如果需要类的不同版本对序列化兼容,要确保类的不同版本具有相同的serialVersionUID如果不需要类的不同版本对序列化兼容,要确保类的不同版本具有不同的serialVersionUID序列化一个类的实例后,如果修改一个字段或者增加一个字段,如果没有设置类的serialVersionUID,就会导致无法反序列化旧的实例,会在反序列化时抛出异常序列化类添加SerialVersionUID后,如果修改一个字段或者增加一个字段,反序列化旧的实例时,修改的或者增加的字段的值会设置为初始化的值破坏单例除了反射可以破坏单例模式外,序列化和反序列化后会得到一个新的对象,也可以破坏单例模式序列化和反序列化破坏单例模式:反序列化时,使用ObjectInputStream对象中的readObject()方法readObject()的方法中调用readObject0()方法readObject0()方法中会返回一个checkResolve(readOrdinaryObject(unshared))readOrdinaryObject()方法用于读取并返回普通对象.这里的普通对象不包括String,Class,ObjectStreamClass,数组或者枚举常量这些对象isInstantiable()方法表示如果一个实现了Serializable接口或者Externalizable接口的类可以在运行时实例化,那么该方法就返回true如果可以在运行时序列化,就会调用desc.newInstance()方法使用反射的方式调用无参构造方法新建一个对象,创建一个类的新的实例如果类实现的是Serializable接口,就调用第一个不可进行序列化超类的无参构造方法数创建新的实例如果类实现的Externalizable接口,就调用公共的无参构造方法创建新的实例isInstantiable()方法表示如果一个实现了Serializable接口或者Externalizable接口的类可以在运行时实例化,那么该方法就返回true如果可以在运行时序列化,就会调用desc.newInstance()方法使用反射的方式调用无参构造方法新建一个对象,创建一个类的新的实例readOrdinaryObject()方法用于读取并返回普通对象.这里的普通对象不包括String,Class,ObjectStreamClass,数组或者枚举常量这些对象readObject0()方法中会返回一个checkResolve(readOrdinaryObject(unshared))反序列化时,使用ObjectInputStream对象中的readObject()方法readObject()的方法中调用readObject0()方法因为序列化过程中会通过反射调用无参构造函数创建一个新的对象,所以序列化会破坏单例模式为了防止序列化破坏单例模式,可以在Singleton.java中添加readResolve()方法并且指定要返回的对象的生成策略因为readOrdinaryObject()方法源码中的hasResolveMethod()表示如果实现了Serializable或者Externalizable接口的类中包含readResolve()方法就返回trueinvokeReadResolve()方法会通过反射的方式调用要被反序列化的类的readResolve()方法作者:攻城狮Chova链接:
目录
- 1 性录像全集
- 2 运河边的人们电视剧在线观看
- 3 养敌为患漫画完整版免费阅读
- ▪ 99zyz
- ▪ 免费现黄频在线观看国产
- 4 中文字幕精品在线
- ▪ 三级午夜三级午夜a影院
- ▪ 你弄得人家里都是水的视频
- 5 校花驾到之极品校花电影
- 6 我的法定老公泰剧全集免费观看
- ▪ 洗屋先生樱花动漫
- ▪ 保姆的快乐
- ▪ VIDEOSSEX变态狂另类
- 7 七号房的礼物电影完整版在线观看
- ▪ 睡着xxxxvideos
- ▪ 回复术士的重启人生樱花在线播放
- ▪ S货你是不是欠C了公交车
- ▪ 长征电视剧免费观看
- ▪ 西行纪之穷奇地洞
- 8 法利赛人
- ▪ 视频二区三区
- ▪ 979游戏中心
- ▪ 国内免费高清视频在线观看
- ▪ 无下装透视十2点后舞蹈视频
- ▪ 善良的锼子5中文字幕
- ▪ 复沐春风花槐
- ▪ 作家的谎言
- ▪ 巨物挺破了校花那层薄膜
- 9 两根一起公憩止痒三十篇
- ▪ 4399最好看的日本韩国电影
- ▪ 4d肉搏团
- ▪ 相爱穿梭千年
- 10 黑人又大又粗又爽免费视频
- ▪ 做错一题进去一次C
- ▪ 说英雄谁是英雄电视剧
- ▪ 国产的一级毛片完整
- ▪ 时光与你别来无恙
- ▪ 半暖时光
- 11 JIZZJIZZJIZZ大学生
- ▪ 久久精品国产在热久久
- ▪ 夏目彩春电影
- ▪ 动漫人物差差差
- ▪ 钢琴教师
- ▪ 金瓶梅1-5电影在线观看完整版
- 12 快喵在线直进官网免费
- 13 蜥蜴先生和乌鸦小姐
- 14 性8论坛
爱情岛亚洲品质论坛路线《爱情岛亚洲品质论坛路线》由来
编辑爱情岛亚洲品质论坛路线《爱情岛亚洲品质论坛路线》起源