Java对象序列化 Object Serialization
来源:互联网 发布:java分布式架构 编辑:程序博客网 时间:2024/05/01 14:57
在最近的一次项目中,从服务器中请求得到了登录用户的相关信息,显然的,需要把其中的信息保存下来。在Android中,持久化保存信息的方式有很多种。比如数据库,首选项,又或者内部存储。但是,这个需要保存的信息字段有些多,目的是方便没网络时也能过显示一些相关的信息。我想到了对象序列化技术,把整个对象保存到磁盘中(内部存储)。
于是,结合网上的文章,及书本上的对应章节,把该知识点记录一下。
想要把一个对象能够被直接保存到数据库或磁盘中,有以下的步骤:
①实现Serializable接口,这是一个声明接口,没有需要实现的方法
public class Person implements Serializable { public static final long serialVersionUID = 1L; private int age; private String password; //other fields //setter and getter }
②保存对象
public void saveObject(Object obj) { FileOutputStream fos = null; ObjectOutputStream oos = null; try { fos = new FileOutputStream("person.dat"); oos = new ObjectOutputStream(fos); oos.writeObject(obj); } catch(Excepton e) { e.printStackTrace(); } finally { //close stream } }
通过上面简单的几句代码,我们就把对象保存下来了。
③读取对象
public Object readObject() { FileInputStream fis = null; ObjectInputStream ois = null; Object obj = null; try { fis = new FileInputStream("person.dat"); ois = new ObjectInputStream(fis); obj = ois.readObject(); } catch(Exception e) { //... } finally { //close stream } return obj; }
通过上面的方法调用我们就把保存的对象从物理媒介中读取了出来
简单的序列化调用这样即可。当然,还需要理解关键字 transient
的意思,它表示当序列化时,请把我忽略;同时,静态字段static
也不会被序列化。
如果我们想保存某个对象时,需要修改,加密某些字段,应该要如果做?我们当然可以额外的在在保存时加密,取出来时再解密。但序列化机制提供了这样的方法截点。即,如果声明了Serializable
的类中有实现private void writeObject(ObjectOutputStream oos);
则保存时会调用该方法,而不是默认的调用ObjectOutputStream#defaultWriteObject()
方法;如果实现了private void readObject(ObjectInputStream ois);
方法,则读取时会调用该方法,而不是默认的ObjectInputStream#defaultReadObject()
方法。当然推荐的是,当我们自己实现这两个方法时,首要的是调用默认的实现。我们举个例子,我们要对Person中的password字段加密后再保存,因为当对象保存到本地时,是可以轻易的读取出来的。
例子:
public class Person implements Serializable { public static final long serialVersionUID = 1L; private String password; //other fields //other methods private void writeObject(ObjectOutputStream oos) { this.password = encrypt(this.password); try { oos.defaultWriteObject(); } catch(Exception e) {} } private void readObject(ObjectInputStream ois) { try { ois.defaultReadObject(); this.password = decrypt(this.password); } catch(Exception e) {} } }
.
嗯,解决完这个问题。再来看一个序列化对象版本的问题。当读取一个序列号对象时,如果没有设置静态常量字段serialVersionUID
,则虚拟机会根据类的相关信息动态生成一个新的版本号,这可能会导致类不兼容,引发InvalidClassException
异常抛出。serialVersionUID
的值可以自己随意设置,或者使用serialver工具生成,或者Eclipse中有智能提示,或者设置Android Studio自动生成。
再来看一个问题,假如我们这个对象的实例是Singleton单例模式,但是我们读取对象时是新建了一个对象,显然是不符合我们的需求的。所以,我们再看一下另一个方法private Object readResolve();
这个方法也是写在声明了Serializable
的类里边。该方法的特性是:
对于一个正在被反序列化的对象,如果它的类定义了一个readObject方法,并且具备正确的声明,那么在反序列化之后,新建对象上的readResolve方法就会被调用。然后,该放方法返回的对象引用将被返回,取代新对象。
所以,我们可以在该方法中返回单例对象。
.
另外,这里引申出一个简单的用法,即深度克隆一个对象:
public Object cloneObject(Object srcObj) { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bout); out.writeObject(srcObj); out.close; ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); ObjectInputStream in = new ObjectInputStream(bin); Object ret = in.readObject(); return ret; }
.
对于简单的序列化用法,有几点总结:
①显示声明序列化版本号serialVersionUID
②保护性地编写readObject方法,比如某些字段不能为null
- Java对象序列化(Object Serialization)
- Java对象序列化 Object Serialization
- android-java对象序列化Object serialization
- 对象序列化(Object Serialization)
- Java源码——对象序列化(对象的存储及读取)(Object Serialization)
- C++ / QT 对象序列化(Object Serialization)的实现
- 浅析Java Object Serialization与 Hadoop 序列化
- 浅析Java Object Serialization与 Hadoop 序列化
- Java Serialization 序列化
- Java 网络编程 之 传输对象 Serialization 序列化
- java serialization/deserialization (序列化对象自描述)
- java中对象序列化(Serialization)的注意事项
- java serialization--java序列化
- Java的序列化(Serialization)
- java中的序列化 serialization
- 初探Java序列化(Serialization)
- Java 的序列化 (Serialization)
- 对象序列化之Boost.Serialization
- 生命周期该干的事
- UVA 12283 Halloween Costumes(区间DP)
- Javascript 中 作用域、闭包与 this 指针
- win32控制台输出带中文Unicode字符串
- Acm 导弹拦截
- Java对象序列化 Object Serialization
- 加急审核
- 2016/08/20 继承练习题(2)
- Ignatius and the Princess III(n的m划分)
- 【入门】矩阵乘法
- windows编程(消息机制、消息队列、消息映射、线程同步)笔记windows编程(消息机制、消息队列、消息映射、线程同步)笔记
- Linux Kernel 编译
- 【NOIP2015】神奇的幻方
- Python