对象序列化
来源:互联网 发布:sql通用查询器 编辑:程序博客网 时间:2024/05/09 01:17
1.说明:
面向实现了Serialization接口的对象,可将它们转换成一系列字节,并可在以后完全恢复原来的样子。换句话说,可以在Windows机器上创建一个对象,通过序列化机制,将其通过网络发送给Linux机器,在通过反序列化可将其恢复成原来的样子。
可实现有限持久化—通过序列化机制,转换成字节流写入到磁盘,在需要的时候再取出来。(有限的原因在于它不像存到数据库中的数据,序列化机制需要自己明确指定序列化和组装对象)
2.序列化过程:
- 1.创建某些OutputStream对象
- 2.创建ObjectOutputStream对象,将某些OutputStream对象封装到ObjectOutputStream对象中
- 3.调用writeObject(object)完成对象的序列化
3.反序列化过程:
- 1.创建某些InputStream对象
- 2.创建ObjectInputStream对象,将InputStream对象封装到ObjectInputStream的对象中
- 3.调用readObject()完成反序列化
定义需要序列化的类
package com.zd.java.io.newio.serialization;import java.io.Serializable;/** * 寻找类 * 序列化一个对象,通过网络将其作为文件传送给另一台机器, * 另一台机器只更根据文件目录来重新构造此对象 * Created by ZD on 2017/10/12. */public class Alien implements Serializable{}
序列化对象
package com.zd.java.io.newio.serialization;import java.io.*;/** * 创建和序列化Alien对象 * Created by ZD on 2017/10/12. */public class FreezeAlien { public static void main(String[] args) throws IOException { ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file.x")); Alien zorcon = new Alien(); out.writeObject(zorcon); }}
反序列化
package com.zd.java.io.newio.serialization;import java.io.*;/** * 恢复一个序列化的对象,如果想对其做更多的事,必须保证JVM能在本地类路径或者 * 因特网的其他什么地方找到相关的class文件 * Created by ZD on 2017/10/12. */public class ThawAlien { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream in = new ObjectInputStream(new FileInputStream("file.x")); Object mystery = in.readObject(); System.out.println(mystery.getClass().toString()); }}
4.序列化的控制:
只序列化对象的一部分,其他部分不序列化,因为对象恢复后,那一部分需要重新构建。下面列出几种方式
4.1ExternalSerializable:
在Serializable的基础上扩展了,新增方法writeExternal()和readExternal(),在序列化和重新装配过程中会优先调用这俩个方法。
package com.zd.java.io.newio.serialization;import java.io.*;/** *保存和恢复一个Externalizable对象必须要做的全部事情 * 恢复对象时会调用默认构造函数,在调用readExternal方法。保存对象会调用writeExternal方法 * Created by ZD on 2017/10/12. */public class Blip3 implements Externalizable{ int i; String s; public Blip3(){ System.out.println("Blip3 constructor"); } public Blip3(String x,int a){ System.out.println("Blip3(String z,int a)"); s = x; i = a; } public String toString(){ return s + i; } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println("blip3.writeExternal"); out.writeObject(s); out.writeInt(i);//写入对象的重要数据 } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("Blip3.readExternal"); s = (String) in.readObject(); i = in.readInt();//恢复数据 } public static void main(String[] args){ System.out.println("constructing objects:"); Blip3 blip3 = new Blip3("a string",47); System.out.println(blip3.toString()); try { ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("Blip3.out")); System.out.println("saving object"); o.writeObject(blip3); o.close(); ObjectInputStream in = new ObjectInputStream(new FileInputStream("Blip3.out")); System.out.println("recovering b3:"); blip3 = (Blip3) in.readObject(); System.out.println(blip3.toString()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}
说明:使用ExternalSerializable,重新组装对象需要调用默认构建函数,再调用readExternal()方法,序列化对象时会调用writeExternal()方法,在这俩个方法中均需要对重要数据进行操作。如果不进行操作,对象成员数据为成默认数据,操作可能会出现问题。
4.2transient(临时)关键字:
对象中如果存在敏感部分,比如登录中的密码,我们不希望它在序列化过程中被保存下来,因为可能会被别人盗取。一种办法是采用ExternalSerializable,只有在writeObject()中明确序列化,否则不保存。另一种办法采用transient关键字。
做法:实现Serializable接口,将不想序列化的字段设置成transient
package com.zd.java.io.newio.serialization;import java.io.*;import java.util.Date;/** * 使用transient进行序列化控制 * 除密码外其他会话信息需要保存下来 * Created by ZD on 2017/10/12. */public class Logon implements Serializable{ private Date date = new Date(); private String username; private transient String password;//transient不会被保存到磁盘 Logon(String name,String pwd){ username = name; password = pwd; } public String toString(){ String pwd = (password == null)?"(n/a)":password; return "logon info: \n"+ "username:"+username+ "\n date:"+date.toString()+ "\n password:"+pwd; } public static void main(String[] args){ Logon a = new Logon("hulk","mylittlepony"); System.out.println("logon a = "+a); try { ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("Logon.out")); o.writeObject(a); o.close(); //delay int seconds = 5; long t = System.currentTimeMillis()+seconds*1000; while (System.currentTimeMillis() < t); ObjectInputStream in = new ObjectInputStream(new FileInputStream("Logon.out")); System.out.println("recovering object at "+new Date()); a = (Logon) in.readObject(); System.out.println("logon a = "+a); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}
执行结果:logon a = logon info: username:hulk date:Sat Oct 14 11:04:34 CST 2017 password:mylittleponyrecovering object at Sat Oct 14 11:04:40 CST 2017logon a = logon info: username:hulk date:Sat Oct 14 11:04:34 CST 2017 password:(n/a)
4.3ExternalSerializable替代方法:
可以实现Serializable接口,并在类中添加俩个方法:writeObject()、readObject(),方法需要有正确的签名:
private void writeObject(ObjectOutputStream stream)throws IOException;
private void readObject(ObjectIutputStream stream)throws IOException;
package com.zd.java.io.newio.serialization;import java.io.*;/** * 使用Serializable实现Externalizable的功能 * 不管是否有transient关键字,优先使用writeObject、readObject * Created by ZD on 2017/10/12. */public class SerialCtl implements Serializable { String a; transient String b; public SerialCtl(String aa,String bb){ a = "not transient:"+aa; b = "transient"+bb; } public String toString(){ return a + "\n" +b; } private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject();//必须调用 stream.writeObject(b); } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); b = (String) stream.readObject(); } public static void main(String[] args){ SerialCtl sc = new SerialCtl("test1","test2"); System.out.println("before:\n"+sc); ByteArrayOutputStream buf = new ByteArrayOutputStream(); try { ObjectOutputStream o = new ObjectOutputStream(buf); o.writeObject(sc);//必须检查sc,判断它是否有自己的writeObject()方法 ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray())); SerialCtl sc2 = (SerialCtl) in.readObject(); System.out.println("a filter:\n"+sc2); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}
5.总结:
序列化方案:
1.实现Serializable接口,自动序列化writeObject(Object object)方法中定义的object,重新组装时是从InputStream中读入的字节进行重新组装对象
2.实现ExternalSerializable接口,在writeExternal()方法中指定需要进行序列化的字段,在 readExternal()方法中指定需要重新组装的字段,组装对象时,调用的是默认构造函数。
3.transient关键字,实现Serializable接口,对不需要序列化的字段声明为transient
4.使用Serializable替代ExternalSerializable接口,在类中添加readObject()、writeObject()方法。
- Java对象序列化
- 对象序列化
- Java对象序列化
- 对象序列化笔记
- 对象的序列化
- 对象序列化
- 对象序列化
- Java对象序列化
- Java对象序列化
- java对象序列化
- Java 对象序列化
- 对象的序列化
- 序列化ArcEngine对象
- 对象序列化
- Java 对象序列化
- Java对象序列化
- 序列化对象传输
- 序列化对象
- 初赛复习6
- usb 3.0
- Wannafly挑战赛1 A.Treepath
- new出来的对象无法调用@Autowired注入的Spring Bean
- 用python实现希尔排序(shell_sort)
- 对象序列化
- nginx 动静分离实现负载均衡
- class属性标签操作记录
- ios下使用speex进行音频压缩
- 会员卡系统
- eclipse安装离线插件后可能不会重新加载的解决办法
- cmd下ftp登陆成功却ls显示Can't build data connection: Connection timed out
- [agc010d]Decrementing
- 变量在进行计算时类型转换问题