沈阳建站免费模板,网站开发博客,一个做智能化的网站有哪些,通州区住房和城乡建设部网站首先需要明确的概念: 序列化#xff1a;将数据结构或对象转换成二进制字节流的过程反序列化#xff1a;将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程持久化#xff1a;将数据写入文件中长久保存的过程称之为持久化序列化主要目的#xff1a;是… 首先需要明确的概念: 序列化将数据结构或对象转换成二进制字节流的过程反序列化将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程持久化将数据写入文件中长久保存的过程称之为持久化序列化主要目的是通过网络传输对象或者说是将对象存储到文件系统、数据库、内存中。 序列化反序列化实例
1.创建一个学生类实现Serializable接口:
public class Student implements Serializable {private String stuNum;private String stuName;//学生拥有多个老师 用集合装private ListString teacherList;public Student() {}public Student(String stuNum, String stuName, ListString teacherList) {this.stuNum stuNum;this.stuName stuName;this.teacherList teacherList;}Overridepublic String toString() {return Student{ stuNum stuNum \ , stuName stuName \ , teacherList teacherList };}public String getStuNum() {return stuNum;}public void setStuNum(String stuNum) {this.stuNum stuNum;}public String getStuName() {return stuName;}public void setStuName(String stuName) {this.stuName stuName;}public ListString getTeacherList() {return teacherList;}public void setTeacherList(ListString teacherList) {this.teacherList teacherList;}
}2.创建SerializableUtil工具类实现序列化反序列化方法
public class SerializableUtil {/*** 将对象序列化到指定文件中* param obj* param fileName* throws IOException*/public static void mySerialize(Object obj, String fileName) throws IOException {OutputStream out new FileOutputStream(fileName);//对象序列化反序列化的流ObjectOutputStream objOut new ObjectOutputStream(out);//将指定对象写入ObjectOutStreamobjOut.writeObject(obj);//关闭流objOut.close();}/*** 从指定文件中反序列化对象* param fileName* return* throws IOException* throws ClassNotFoundException*/public static Object myDeserialize(String fileName) throws IOException, ClassNotFoundException {InputStream in new FileInputStream(fileName);ObjectInputStream objIn new ObjectInputStream(in);Object obj objIn.readObject();return obj;}
}3.SerializableTest测试类测试序列化反序列化实现
public class SerializableTest {public static void main(String[] args) {ListString teacherList new ArrayList();teacherList.add(王老师);teacherList.add(张老师);Student stu1 new Student(1001, 张三, teacherList);System.out.println(原始对象 stu1);String fileName stu01.txt;try {//对象序列化SerializableUtil.mySerialize(stu1, fileName);System.out.println(序列化原始对象完成OK);//对象的反序列化Object obj SerializableUtil.myDeserialize(fileName);//确定obj是Student类型if (obj instanceof Student) {Student stuNew (Student) obj;System.out.println(反序列化之后的对象 stuNew);}} catch (Exception e) {e.printStackTrace();}}
}4.测试结果: 生成stu01.txt文件将数据结构成功转为二进制字节流存入文件中: 部分属性序列化和反序列化的四种方法
Transient关键字修饰 private transient String stuNum;private transient String stuName;//学生拥有多个老师 用集合装private ListString teacherList;测试结果: 这里的stuNum和StuName反序列化后就是默认值null,因为经过了transient修饰阻止了属性的实例化,因此反序列结果中是null。 对于不想进行序列化的变量可以使用 transient 关键字修饰。 transient 关键字的作用是让实例中的属性不再序列化当对象被反序列化时被 transient 修饰的属性不会被持久化和恢复。需要注意的一些点
transient关键字只能修饰属性不能修饰方法和类。transient关键字修饰的属性变量在经过反序列化之后会是相应类型的默认值例如String类型反序列化后就是是nullint类型反序列化后就是0。 Static关键字修饰
测试: private String stuNum;private static String stuName;//学生拥有多个老师 用集合装private ListString teacherList;public static void main(String[] args) {ListString teacherList new ArrayList();teacherList.add(王老师);teacherList.add(张老师);Student stu1 new Student(1001, 张三, teacherList);System.out.println(原始对象 stu1);String fileName stu01.txt;try {//对象序列化SerializableUtil.mySerialize(stu1, fileName);System.out.println(序列化原始对象完成OK);stu1.setStuName(张三他爹);//对象的反序列化Object obj SerializableUtil.myDeserialize(fileName);//确定obj是Student类型if (obj instanceof Student) {Student stuNew (Student) obj;System.out.println(反序列化之后的对象 stuNew);}} catch (Exception e) {e.printStackTrace();}}测试结果: 这里通过用static关键字修饰直接在完成初始序列化后set.stuName可以改变学生名字因为static修改的属性变量不属于任何对象是静态的因此无论使用transient与否都不会被序列化。 修改默认方法writeObject和readObject
在Serializable接口源码中有这样的说明
大概翻译一下writeObject和readObject
测试:
public class Student implements Serializable {private String stuNum;private String stuName;private ListString teacherList;private void writeObject(ObjectOutputStream objOut) throws IOException {System.out.println(writeObject-----------);objOut.writeObject(stuNum);objOut.writeObject(stuName);}private void readObject(ObjectInputStream objIn) throws IOException,ClassNotFoundException {System.out.println(readObject-----------);stuNum (String) objIn.readObject();stuName (String) objIn.readObject();}
}测试结果: 因为在writeObject和readObject方法中只序列化和反序列化了stuNum和stuName因此teacherList是没有序列化反序列的所以是String的默认值null Externalizable实现序列化反序列化和部分序列化 Externalizable继承自Serializable使用Externalizable接口需要实现readExternal方法和writeExternal方法来实现序列化和反序列化。 源码部分 代码实现
private String stuNum;private String stuName;//学生拥有多个老师 用集合装private ListString teacherList;Overridepublic void writeExternal(ObjectOutput out) throws IOException {out.writeObject(stuNum);out.writeObject(stuName);}Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {stuNum (String) in.readObject();stuName (String) in.readObject();}测试结果: 同样是因为writeExternal()和readExternal()只序列化和反序列化了stuNum和stuName因此teacherList是没有序列化反序列的所以是String的默认值null Serializable 与 Externalizable
区别SerializableExternalizable实现复杂度实现简单Java对其有内建支持实现复杂由开发人员自己完成执行效率所有对象由Java统一保存性能开发人员决定哪个对象保存可能造成速度提升保存信息保存时占用空间大部分存储可能造成空间减少使用频率高偏低关于序列化问题 Serializable
在修改公司项目的时候遇到这个问题联想起之前做一篇博客。代码红线不贴了。
序列化的概念
序列化把Java对象转换为字节序列的过程。 反序列化把字节序列恢复为Java对象的过程。
序列化的方式
把对象的字节序列永久地保存到硬盘上通常存放在一个文件中持久化对象 在网络上传送对象的字节序列。网络传输对象
如何实现序列化
实现两个接口 Serializable 接口 Externalizable 接口 Serializable接口
一个对象想要被序列化那么它的类就要实现此接口或者它的子接口。 这个对象的所有属性包括private属性、包括其引用的对象都可以被序列化和反序列化来保存、传递。 不想序列化的字段可以使用transient修饰。 由于Serializable对象完全以它存储的二进制位为基础来构造因此并不会调用任何构造函数因此Serializable类无需默认构造函数但是当Serializable类的父类没有实现Serializable接口时反序列化过程会调用父类的默认构造函数因此该父类必需有默认构造函数否则会抛异常。
使用transient关键字阻止序列化虽然简单方便但被它修饰的属性被完全隔离在序列化机制之外导致了在反序列化时无法获取该属性的值而通过在需要序列化的对象的Java类里加入writeObject()方法与readObject()方法可以控制如何序列化各属性甚至完全不序列化某些属性或者加密序列化某些属性。
Externalizable 接口
它是Serializable接口的子类用户要实现的writeExternal()和readExternal() 方法用来决定如何序列化和反序列化。
因为序列化和反序列化方法需要自己实现因此可以指定序列化哪些属性而transient在这里无效。
对Externalizable对象反序列化时会先调用类的无参构造方法这是有别于默认反序列方式的。如果把类的不带参数的构造方法删除或者把该构造方法的访问权限设置为private、默认或protected级别会抛出java.io.InvalidException: no valid constructor异常因此Externalizable对象必须有默认构造函数而且必需是public的。
serialVersionUID
serialVersionUID字段用来控制序列化的版本
一个对象数据在反序列化过程中如果序列化串中的serialVersionUID与当前对象值不同则反序列化失败否则成功。
如果serialVersionUID没有显式生成系统就会自动生成一个。生成的输入有类名、类及其属性修饰符、接口及接口顺序、属性、静态初始化、构造器。任何一项的改变都会导致serialVersionUID变化。
属性的变化都会导致自动生成的serialVersionUID发生变化。例如对于对象A我们生成序列化的S(A)然后修改A的属性则此时A的serialVersionUID发生变化。反序列化时S(A)与A的serialVersionUID不同无法反序列化。会报序列号版本不一致的错误。
实现代码