黄江建设网站,预付的网站开发费用怎么入账,杨浦网站建设,宁波网站推广高手【README】
1#xff0c; 为啥要序列化或序列化的意义#xff1f;2#xff0c;系统间调用的报文格式#xff0c;大多数是Json字符串#xff08;或字节数组#xff09;#xff1b;接收方接收json#xff1b;3#xff0c;但当系统调用如RMI#xff0c;客户端请求服务器…【README】
1 为啥要序列化或序列化的意义2系统间调用的报文格式大多数是Json字符串或字节数组接收方接收json3但当系统调用如RMI客户端请求服务器获取一个 javabean对象的状态信息而不是json格式这个时候 json格式就不合适了当然了在发送时我们可以 把 javabean的状态信息的属性转为json接收时把json对象转为 javabean很显然这样太复杂了而且不利于维护一旦 javabean的属性做修改需要改的代码太多4基于此 序列化出现了序列化可以把对象信息转换为字节数组保存到媒介中如磁盘内存或传输到网络后续需要用到的时候可以直接把字节数组反序列化为java对象而不需要做其他操作也可以理解为是 java对象持久化 这可以解决 系统调用间 javabean对象信息传输的问题即请求前把对象序列化为字节数组接收时把字节数组反序列化直接解析为java bean对象而不需要其他格式转换5序列化的另一个用途是 用于java对象的深拷贝
【补充1】本文给出了3种实现序列化的方式包括
1种自动方式实现 Serializable 接口2种手动方式分别实现 Externalizable Serializable 接口
【补充2】自动实现与手动实现
自动实现 程序员无需自定义字段序列化策略由 java底层默认实现手动实现程序员需要自定义自定序列化策略哪些需要序列化哪些不需要【1】java序列化实现
1java序列化定义 把那些实现了 Serializable 接口的对象转换成一个字节序列并能够在以后把这个字节 序列完全恢复到原来的对象实现对 javabean状态的持久化
2如何理解持久性 持久性意味着一个对象的生命周期并不取决于 程序是否在执行就像数据库的持久化一样但一个对象可以存在于 程序的调用之间如远程方法调用 RMI
3通过序列化可以把java对象以字节格式保存到磁盘内存网络流上面在以后需要的时候把序列化后的字节恢复或反序列化成原来的 javabean的状态 【2】 序列化实现
【2.1】实现 Serializable 接口自动实现序列化 javabean序列化
/*** Description 实现Serializable自动实现序列化与反序列化* author xiao tang* version 1.0.0* createTime 2021年11月20日*/
public class AutoSerializableClass implements Serializable {String name;Date date;MapString, String configs;// transient 表示不序列化agetransient int age;public AutoSerializableClass(String name) {this(name, Collections.emptyMap(), new Date(), 18);}public AutoSerializableClass(String name, MapString, String configs) {this(name, configs, new Date(), 18);}public AutoSerializableClass(String name, MapString, String configs, Date date, int age) {this.name name;this.configs configs;this.date date;this.age age;}public String getName() {return name;}public MapString, String getConfigs() {return configs;}/*** description 基于序列化的深度拷贝* return AutoSerializableClass* author xiao tang* date 2021/11/20*/public AutoSerializableClass deepClone() throws Exception {ByteArrayOutputStream buf new ByteArrayOutputStream();// 把流放在 tyr资源块中程序结束java会自动关闭流资源try (ObjectOutputStream outputStream new ObjectOutputStream(buf)) {outputStream.writeObject(this);}try (ObjectInputStream inputStream new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()))) {return (AutoSerializableClass) inputStream.readObject();}} Overridepublic String toString() {return AutoSerializableClass{ name name \ , date date , configs configs , age age };}
}
【2.1.1】序列化到磁盘与反序列
public static String path d://temp//;
/*** description 测试用例-把 AutoSerializableClass 对象序列化到磁盘* author xiao tang* date 2021/11/20*/public static void main(String[] args) throws IOException, ClassNotFoundException {// 把 AutoSerializableClass 对象序列化到磁盘ObjectOutputStream outputStream new ObjectOutputStream(new FileOutputStream(path my01.out));outputStream.writeObject(new AutoSerializableClass(zhangsan));outputStream.close();// 从磁盘读取序列化对象ObjectInputStream objectInputStream new ObjectInputStream(new FileInputStream(path my01.out));AutoSerializableClass objParsed (AutoSerializableClass) objectInputStream.readObject();System.out.println(objParsed.getName()); // zhangsan}
【2.1.2】深度拷贝
/** * description 测试用例-基于 Serializable接口自动实现序列化的深度拷贝* author xiao tang* date 2021/11/20 */public static void main(String[] args) throws Exception {MapString, String configs new HashMap();configs.put(k1, v1);AutoSerializableClass lisi new AutoSerializableClass(lisi, configs);// 深度拷贝到lisi2 和 lisi3AutoSerializableClass lisi2 lisi.deepClone();AutoSerializableClass lisi3 lisi.deepClone();// 为lisi2添加配置lisi2.getConfigs().put(k2, v2);System.out.println(\n lisi2); // configs{k1v1, k2v2}, age0System.out.println(lisi2);System.out.println(\n lisi3); // configs{k1v1}, age0System.out.println(lisi3);// 为lisi3添加配置lisi3.getConfigs().put(k3, v3);System.out.println(\n lisi2); // configs{k1v1, k2v2}, age0System.out.println(lisi2);System.out.println(\n lisi3); // configs{k1v1, k3v3}, age0 System.out.println(lisi3);} lisi2 AutoSerializableClass{namelisi, dateSat Nov 20 21:43:50 CST 2021, configs{k1v1, k2v2}, age0} lisi3 AutoSerializableClass{namelisi, dateSat Nov 20 21:43:50 CST 2021, configs{k1v1}, age0} lisi2 AutoSerializableClass{namelisi, dateSat Nov 20 21:43:50 CST 2021, configs{k1v1, k2v2}, age0} lisi3 AutoSerializableClass{namelisi, dateSat Nov 20 21:43:50 CST 2021, configs{k1v1, k3v3}, age0} 【代码解说】
1可以看到 lisi2 lisi3 是独立的两个对象且反序列化后lisi2lisi3 定义的 configs 不是同一个 2age 本身初始化为18但这里为0是因为 age 被修改为 transient表示不序列该字段故age取int默认值03接口 Serializable 没有任何方法仅一个标识接口而已【2.2】实现 Externalizable 接口手动实现序列化
1Externalizable接口继承自 Serializable 有2个方法需要实现
2这两个方法 writeExternal 和 readExternal 方法 会分别在序列化和反序列化还原的过程中被自动调用以便执行一些特殊操作对某些字段进行序列化与反序列化某些不进行如账号密码private字段不序列化等 如 我们可以对age 字段进行序列化和反序列化即便age被 transient 修饰
public interface Externalizable extends java.io.Serializable {void writeExternal(ObjectOutput out) throws IOException; void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
3Externalizable 实现类
/*** Description 实现Externalizable手动实现序列化与反序列化* author xiao tang* version 1.0.0* createTime 2021年11月20日*/
public class ManualExternalizableClass implements Externalizable {String name;Date date;MapString, String configs;// transient 表示不序列化agetransient int age;public ManualExternalizableClass(){}public ManualExternalizableClass(String name) {this(name, new Date(), new HashMapString, String(), 18);}public ManualExternalizableClass(String name, Date date, MapString, String configs, int age) {this.name name;this.date date;this.configs configs;this.age age;}/** * description 序列化过程自动调用* param out 序列化书写流* author xiao tang* date 2021/11/20 */Overridepublic void writeExternal(ObjectOutput out) throws IOException {out.writeObject(name);out.writeObject(date);out.writeInt(age);}/** * description 反序列化过程自动调用* param in 反序列化读入流* author xiao tang* date 2021/11/20 */Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {this.name String.valueOf(in.readObject());this.date (Date) in.readObject();this.age in.readInt();}/*** description 深度拷贝 ManualExternalizableClass* return MyExternalizableClass对象* author xiao tang* date 2021/11/20*/public ManualExternalizableClass deepClone() throws Exception {ByteArrayOutputStream buf new ByteArrayOutputStream();try (ObjectOutputStream outputStream new ObjectOutputStream(buf)) {outputStream.writeObject(this);}try (ObjectInputStream inputStream new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()))) {return (ManualExternalizableClass) inputStream.readObject();}}public void setAge(int age) {this.age age;}Overridepublic String toString() {return ManualExternalizableClass{ name name \ , date date , configs configs , age age };}
}
【2.2.1】 测试用例对 Externalizable 对象进行深拷贝
/*** Description 测试用例-实现Externalizable手动实现序列化与反序列化* author xiao tang* version 1.0.0* createTime 2021年11月20日*/
public class ManualExternalizableClassTest {public static void main(String[] args) throws Exception {ManualExternalizableClass obj new ManualExternalizableClass(zhangsan);// 深度拷贝ManualExternalizableClass newObj obj.deepClone();newObj.setAge(19); // 对新对象的age赋值不影响老对象System.out.println(obj obj); // age18System.out.println(newObj newObj); // age19}
}obj MyExternalizableClass{namezhangsan, dateSat Nov 20 20:32:15 CST 2021, configs{}, age18} newObj MyExternalizableClass{namezhangsan, dateSat Nov 20 20:32:15 CST 2021, configsnull, age19} 【代码解说】
1上述javabean MyExternalizableClass实现了 Externalizable 接口的方法 writeExternal() 序列化字段name,date, age实现了方法 readExternal()反序列化字段 name, date, age即便age 被 transient 修饰但我们还可以序列化2这种方式的序列化需要指定序列化的字段本文定义为 手动序列化方式【2.3】实现Serializable手动实现序列化
1序列化javabean
/*** Description 实现 Serializable 手动实现序列化与反序列化* author xiao tang* version 1.0.0* createTime 2021年11月20日*/
public class ManualSerializableClass implements Serializable {String name;Date date;MapString, String configs;// transient 表示不序列化agetransient int age;public ManualSerializableClass(String name) {this(name, new HashMap(), new Date(), 18);}public ManualSerializableClass(String name, MapString, String configs) {this(name, configs, new Date(), 18);}public ManualSerializableClass(String name, MapString, String configs, Date date, int age) {this.name name;this.configs configs;this.date date;this.age age;}public String getName() {return name;}public MapString, String getConfigs() {return configs;}/** * description 序列化过程自动调用注意这里并不是重写 Serializable接口方法即便没有重写序列化过程也会自动调用算是java一个缺陷from thingking-in-java* param outputStream 书写流* author xiao tang* date 2021/11/20 */private void writeObject(ObjectOutputStream outputStream) throws IOException {outputStream.defaultWriteObject(); // 先调用默认序列化方式outputStream.writeInt(age); // 把age 进行手动序列化}/** * description 反序列化过程自动调用注意这里并不是重写 Serializable接口方法即便没有重写反序列化过程也会自动调用算是java一个缺陷from thingking-in-java* param inputStream 读入流* author xiao tang* date 2021/11/20 */private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {inputStream.defaultReadObject(); // 先调用默认反序列化方式age inputStream.readInt(); // 把 age 手动反序列化}/*** description 基于序列化的深度拷贝* return AutoSerializableClass* author xiao tang* date 2021/11/20*/public ManualSerializableClass deepClone() throws Exception {ByteArrayOutputStream buf new ByteArrayOutputStream();try (ObjectOutputStream outputStream new ObjectOutputStream(buf)) {outputStream.writeObject(this);}try (ObjectInputStream inputStream new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()))) {return (ManualSerializableClass) inputStream.readObject();}}Overridepublic String toString() {return AutoSerializableClass{ name name \ , date date , configs configs , age age };}
}
2测试用例
/*** Description 测试用例-实现 Serializable 手动实现序列化与反序列化* author xiao tang* version 1.0.0* createTime 2021年11月20日*/
public class ManualSerializableClassTest {public static void main(String[] args) throws Exception {ManualSerializableClass oldObj new ManualSerializableClass(zhangsan);ManualSerializableClass newObj oldObj.deepClone();newObj.getConfigs().put(newK, newV);System.out.println(oldObj oldObj); // configs{}, age18System.out.println(newObj newObj); // configs{newKnewV}, age18}
} oldObjMySerializableClass{namezhangsan, dateSat Nov 20 21:06:37 CST 2021, configs{}, age18} newObjMySerializableClass{namezhangsan, dateSat Nov 20 21:06:37 CST 2021, configs{newKnewV}, age18} 【小结】