编程语言的基础——搞定JavaIO (7)

对于java bean,一定要保存下来它在设计阶段对他的状态信息的配置,在程序启动时进行后期恢复,这中具体工作就是由对象序列化完成的。

+package javaS.IO; /** * Serializable为标记接口,表示这个类的对象可以被序列化。 * * @author Evsward * */ public class Student extends IOBaseS implements Serializable { /** * 类中的声明 * * transient和static的变量不会被序列化 */ /** * 序列号:避免重复序列化 * 如果serialVersionUID被修改,反序列化会失败。 * 当程序试图序列化一个对象时,会先检查该对象是否已经被序列化过,只有该对象从未(在本次虚拟机中)被序列化,系统才会将该对象转换成字节序列并输出。 */ private static final long serialVersionUID = -6861464712478477441L; private long id; private String name; private int age; private transient double height; public Student() { } public Student(long id, String name, int age, double height) { super(); this.id = id; this.name = name; this.age = age; this.height = height; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("id:"); sb.append(this.id); sb.append(" "); sb.append("name:"); sb.append(this.name); sb.append(" "); sb.append("age:"); sb.append(this.age); sb.append(" "); sb.append("height:"); sb.append(this.height); return sb.toString(); } /** * 相当于重写了ObjectOutputStream.writeObject方法,ObjectOutputStream写入该对象的时候会调用该方法 * * 作用:可以在序列化过程中,采用自定义的方式对数据进行加密 * * 参考源码: * * public final void writeObject(Object obj) throws IOException { if (enableOverride) {// 如果发现参数Object有重写该方法,则去执行重写的方法,否则继续执行本地方法。 writeObjectOverride(obj); return; } try { writeObject0(obj, false); } catch (IOException ex) { if (depth == 0) { writeFatalException(ex); } throw ex; } } * * * readObject方法的分析同上。 * * @param out * @throws IOException */ private final void writeObject(ObjectOutputStream out) throws IOException { logger.info("Start writing data to Object."); out.writeLong(this.id); /** * 下面的writeObject是StringBuffer源码中的: * * readObject is called to restore the state of the StringBuffer from a stream. private synchronized void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { java.io.ObjectOutputStream.PutField fields = s.putFields(); fields.put("value", value); fields.put("count", count); fields.put("shared", false); s.writeFields(); } */ out.writeObject(new StringBuffer(name)); out.writeInt(this.age); out.writeDouble(this.height);// 这里重写以后,就忽略了transient的设置 } private final void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { logger.info("Start reading data to Object."); this.id = in.readLong(); /** * 下面的readObject是StringBuffer源码中的: * * readObject is called to restore the state of the StringBuffer from a stream. private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { java.io.ObjectInputStream.GetField fields = s.readFields(); value = (char[])fields.get("value", null); count = fields.get("count", 0); } */ this.name = ((StringBuffer) in.readObject()).toString(); this.age = in.readInt(); this.height = in.readDouble(); } }

这个类内容比较多,因为为了更好的去分析,我将jdk的源码也粘贴到注释区域了。但是不影响,文末会有源码位置,感兴趣的同学可以去下载源码查看。在这个类中,我们重写了readObject和writeObject方法,外部ObjectXXXStream在调用的时候会先找对象类中是否有重写的readObject和writeObject方法,如果有则使用没有才调用自己内部默认的实现方法。

package javaS.IO; +import java.io.FileInputStream; /** * 研究对象序列化(跨平台,跨网络的基础) * * 内存 -> 磁盘/网络 * * Java对象 -> 二进制文件 * * @author Evsward * */ public class ObjectStreamS extends IOBaseS { /** * ObjectOutputStream:对象流(对象序列化),不同于DataOutputStream是操作基本类型。 * 测试序列化对象存储结构 */ @Test public void testWriteSerialObject() throws IOException { FileS.initEV(root + "/access");// 先将access文件清空。 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(root + "/access")); Student Lu = new Student(2001, "Luxa", 31, 1.81d); // 可以写入不同的序列化对象数据,但要记录写入顺序 oos.writeObject(Lu); oos.close(); /** * access内容:由于写入的是一个二进制文件,所以打开是乱码 * * ¬í^@^Esr^@^PjavaS.IO.Student Ç.2<95>׳^?^B^@^DI^@^CageD^@^FheightJ^@^BidL^@^Dnamet^@^RLjava/lang/String;xp^@^@^@^_?üõÂ<8f>\(ö^@^@^@^@^@^@^GÑt^@^DLuxa */ } /** * ObjectInputStream:对象反序列化 * 读取二进制文件(序列号文件) * * @throws IOException * @throws ClassNotFoundException */ @Test public void testReadSerialObject() throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(root + "/access")); // 可以读取不同的对象的数据,但是要按照写入顺序去读取。 Student s = (Student) ois.readObject(); logger.info(s); ois.close(); /** * ①输出: * * 10:24:08[testReadSerialObject]: id:2001 name:Luxa age:31 height:1.81 * * ②若height属性变量被声明为transient,则该变量在序列化过程中不会被写入,为初始值。输出为: * * 10:29:34[testReadSerialObject]: id:2001 name:Luxa age:31 height:0.0 */ } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzxpgs.html