做外贸网站的公司,搜索网址的浏览器,wordpress 目录标签化,泉州百度首页优化对象序列化#xff08;object serialization#xff09;是java支持的通用机制#xff0c;可以将任何对象写出到流中#xff0c;并在之后将其回读。简单来说#xff0c;就是可以将对象数据保存为文件#xff0c;甚至可以通过网络传输#xff0c;在这之后或者别的主机上恢… 对象序列化object serialization是java支持的通用机制可以将任何对象写出到流中并在之后将其回读。简单来说就是可以将对象数据保存为文件甚至可以通过网络传输在这之后或者别的主机上恢复当前保存的数据状态。
序列化把Java对象转换为字节序列的过程反序列把字节序列恢复为Java对象的过程
序列化方式
序列化方式Serializable接口和Externalizable接口两种方式。 1.Seriallizable接口 Serializable接口是一个标记接口没有方法或字段。一旦实现了此接口就标志该类的对象就是可序列化的。
public interface Serializable {
}2.Externalizable接口 Externalizable继承了Serializable接口还定义了两个抽象方法writeExternal()和readExternal()如果开发人员使用Externalizable来实现序列化和反序列化需要重写writeExternal()和readExternal()方法
public interface Externalizable extends java.io.Serializable {void writeExternal(ObjectOutput out) throws IOException;void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}Java序列化常用API
java.io.ObjectOutputStream
java.io.ObjectInputStream
java.io.Serializable
java.io.Externalizablejava.io.ObjectOutputStream类
表示对象输出流它的writeObject(Object obj)方法可以对指定obj对象参数进行序列化再把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream
表示对象输入流它的readObject()方法从输入流中读取到字节序列反序列化成为一个对象最后将其返回。
序列化ID
Java提供了两种方式来生成序列化ID默认方式和自定义方式。 1.如果类没有显式声明serialVersionUID字段Java会根据类的结构信息自动生成一个序列化ID。生成算法通常是基于类的名称、字段、方法等生成一个哈希值。 2.如果类显式声明了serialVersionUID字段Java会使用该字段的值作为序列化ID。
import java.io.Serializable;class Person implements Serializable {
//默认方式生成序列化IDprivate static final long serialVersionUID 1L;private String name;private int age;// constructor, getters, setters, etc.
}class Person implements Serializable {
//自定义方式生成IDprivate static final long serialVersionUID 123456789L;private String name;private int age;// constructor, getters, setters, etc.
} 实现Serializable接口时不是必须要有Serializable id但建议为每个可序列化的类都提供一个Serializable id。这个id可以保证在序列化和反序列化过程中对象的唯一性和一致性。如果没有提供Serializable idJava会自动生成一个id但这样可能会导致在不同的JVM中生成的id不一致从而导致序列化和反序列化失败。因此为了保证可序列化类的兼容性和稳定性建议为每个可序列化的类都显式地提供一个Serializable id。
在进行Java序列化时需要注意如下事项
1类要实现序列化功能只需实现java.io.Serializable接口即可 2在进行序列化和反序列化时必须保持序列化ID的一致一般使用private static final long serialVersionUID定义序列化ID 3序列化并不保存静态变量 4在需要序列化父类变量时父类也需要实现Serilizable接口 5使用Transient关键字可以阻止该变量被序列化在被反序列化后transient变量的值被设置为对应类型的初始值。例如int类型变量的是0Object类型变量的值是null 具体的序列化实现代码如下
import java.io.Serializable;
//通过实现Serializable接口定义可序列化的Worker类
public class Worker implements Serializable{//定义序列化的IDprivate static final long serialVersionUID 123456789L;//name属性将被序列化private String name;//transient修饰的变量不会被序列化private transient int salary;//静态变量属于类信息不属于对象的状态因此不会被序列化static int age100;public String getName(){return name;}public void setName(String name){this.name name;}}
注意transient修饰的属性和static修饰的静态属性不会被序列化。 对象通过序列化后在网络上传输基于网络安全我们可以在序列化前将一些敏感字段用户名、密码、身份证号使用密钥进行加密在反序列化后再基于密钥对数据进行解密。这样即使数据在网络中被劫持由于缺少密钥也无法对数据进行解析这样可以在一定程度上保持序列化对象的数据安全。 我们可以基于JDK原生的ObjectOutputStream和ObjectInputStream类实现对象的序列化及反序列化并调用其writeObject()和readObject()方法实现自定义序列化策略。具体的实现代码如下
import java.io.*;
import java.lang.reflect.*;
import java.util.*;public class Main {public static void main(String[] args) throws Exception {//序列化数据到磁盘long serializationstartTime System.currentTimeMillis();FileOutputStream fos new FileOutputStream(work.out);ObjectOutputStream oos new ObjectOutputStream(fos);for(int i0;i5000000;i){Worker testObject new Worker();testObject.setName(alexi);oos.writeObject(testObject);}oos.flush();oos.close();long serializationEndTime System.currentTimeMillis();System.out.println(String.format(java serialization user time:%d,(serializationEndTime-serializationstartTime)));//反序列化磁盘数据并解析数据状态FileInputStream fis new FileInputStream(work.out);ObjectInputStream ois new ObjectInputStream(fis);Worker worker null;try{while((worker (Worker) ois.readObject())!null){//worker为反序列化后的对象}}catch(EOFException e){ //在文件读取完成时会抛出EOFException}long deserializationEndTime System.currentTimeMillis();System.out.println(String.format(java deserialization use timme:%d,(deserializationEndTime-serializationEndTime)));}}
实际开发中实现对象的序列化通常使用的是第三方工具而不是JDK原生的ObjectOutputStream和ObjectInputStream类。
序列化的应用
1.序列化机制可以将对象保存到硬盘上减轻内存压力也起到了持久化的作用。 2.序列化机制是Java对象实现在RPC(远程过程调用或者网络中传输。 注序列化在实际使用过程中除了使用Java的序列化技术来实现还可以使用FastJson等序列化框架来实现。
相关问题
1.serialVersionUID有什么用 JAVA序列化的机制是通过判断类的serialVersionUID来验证版本是否一致的。在进行反序列化时JVM会把传来的字节流中的serialVersionUID和本地相应实体类的serialVersionUID进行比较如果相同反序列化成功如果不相同就抛出InvalidClassException异常。
2.为什么需要手动指定serialVersionUID 在Java中当一个类实现了Serializable接口并需要进行序列化和反序列化操作时Java会自动生成一个默认的serialVersionUID。但是由于默认的serialVersionUID是基于类的内部结构自动生成的因此当类的内部结构发生改变时serialVersionUID的值也会发生变化。这就会导致序列化和反序列化操作时版本不匹配的问题从而无法正确地反序列化对象。 为了避免这个问题可以手动指定一个稳定的serialVersionUID。手动指定serialVersionUID可以确保在类的内部结构发生变化时serialVersionUID的值不会改变从而保证对象的序列化和反序列化操作的正确性。 需要注意的是如果两个类的serialVersionUID相同但是它们的实现并不兼容比如字段数量或类型不同则在反序列化时也会出现问题。因此即使serialVersionUID相同也不能保证两个类可以相互转换。
注意实际开发中不要随意修改serialVersionUID阿里巴巴开发手册中第四章OOP规约的第13条解释如下
【强制】序列化类新增属性时请不要修改serialVersionUID字段避免反序列失败如果 完全不兼容升级避免反序列化混乱那么请修改serialVersionUID值。说明注意serialVersionUID不一致会抛出序列化运行时异常。4.为什么不推荐jdk自带的序列化
不支持跨语言调用 : 如果调用的是其他语言开发的服务的时候就不支持了。性能差相比于其他序列化框架性能更低主要原因是序列化之后的字节数组体积较大导致传输成本加大。存在安全问题序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制那么攻击者即可通过构造恶意输入让反序列化产生非预期的对象在此过程中执行构造的任意代码。
5.在 Java 中,Serializable 和 Externalizable 有什么区别 Externalizable继承了Serializable给我们提供 writeExternal() 和 readExternal() 方法, 让我们可以控制 Java的序列化机制, 不依赖于Java的默认序列化。正确实现 Externalizable 接口可以显著提高应用程序的性能。
6.序列化时如何让某些成员不要序列化 可以用transient关键字修饰它可以阻止修饰的字段被序列化到文件中在被反序列化后transient 字段的值被设为初始值比如int型的值会被设置为 0对象型初始值会被设置为null static静态变量和transient 修饰的字段是不会被序列化的。静态static成员变量是属于类级别的而序列化是针对对象的。transient关键字修字段饰可以阻止该字段被序列化到文件中。
7.如果要序列化的不同对象其属性都指向了同一个对象怎么办 对此Java核心卷2的解释是每个对象都是用一个序列号serial number来保存的。也就是说序列化的每个对象关联的都是一个序列号而不再是运行时的内存地址。 处理的具体算法为 保存对象
每个对象引用都关联一个序列号对每个对象第一次遇到时保存其输出对象到输出流中如果某个对象之前已经被保存过那么只写出“与之前保存过的序列号为x的对象相同”
恢复对象 通过读回恢复对象整个过程反过来。 对于输入流中的对象在第一次遇到其序列号时构建它并使用流中数据初始化它然后记录这个顺序号和新对象之间的关联。 当遇到“与之前保存过的序列号为x的对象相同”标记时获取与这个顺序号相关联的对象引用。
8.如果子类实现了子类实现了Serializable接口父类没有实现Serializable接口的话父类不会被序列化。反序列化时子类的父类属性就会丢失。 9.序列化是针对对象的故static成员变量属于类级别不能被序列化。如果某个序列化类的成员变量是对象类型则该对象类型的类必须实现序列化。 10.序列化机制提供了一种克隆对象的简单途径只要对应的类是可序列化即可。做法很简单直接将对象序列化到输出流中然后将其读回。这样产生的新对象是对现有对象的一个深拷贝。在此过程中我们不必将对象写出到文件中因为可以用ByteArrayOutputStream将数据保存到字节数组中。虽然这个方法很灵巧但它通常会比显示地构建新对象并复制或克隆数据域的克隆方法慢得多。
关于浅拷贝、深拷贝、序列化实现深拷贝的参考
https://blog.csdn.net/demo_yo/article/details/116159275
https://blog.csdn.net/m0_37128231/article/details/81912327