java 调用oracle序列化_Java序列化(含transient)

本文详细介绍了Java对象的序列化过程,包括默认序列化机制、自定义序列化协议,以及如何处理序列化过程中遇到的问题。通过示例展示了如何在类中使用`transient`关键字以及如何处理反序列化时的构造函数行为。同时,文章还讨论了序列化的陷阱,如修改对象状态后的无效序列化和版本控制问题,并提供了解决方案。
摘要由CSDN通过智能技术生成

什么是序列化?

我们创建的对象只有在Java虚拟机保持运行时,才会存在于内存中。如果想要超出Java虚拟机的生命周期,就可以将对象序列化,将对象状态转换为字节序列,写入文件(或socket传输),后面使用时再读入文件,读入原始字节并创建一个完全相同的对象。

PS:只有对象的状态会被序列化,类本身或方法都不会被序列化。

三种序列化方式

1、默认机制

需要序列化的对象,实现java.io.Serializable接口即可。

例子:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

importjava.io.Serializable;importjava.util.Date;importjava.util.Calendar;public class PersistentTime implementsSerializable {privateDate time;publicPersistentTime() {

time=Calendar.getInstance().getTime();

}publicDate getTime() {returntime;

}

}importjava.io.ObjectOutputStream;importjava.io.FileOutputStream;importjava.io.IOException;public classFlattenTime {public static voidmain(String[] args) {

String filename= "time.ser";if (args.length > 0) {

filename= args[0];

}

PersistentTime time= newPersistentTime();

FileOutputStream fos= null;

ObjectOutputStream out= null;try{

fos= newFileOutputStream(filename);

out= newObjectOutputStream(fos);

out.writeObject(time);

out.close();

}catch(IOException ex) {

ex.printStackTrace();

}

}

}importjava.io.ObjectInputStream;importjava.io.FileInputStream;importjava.io.IOException;importjava.util.Calendar;public classInflateTime {public static voidmain(String[] args) {

String filename= "time.ser";if (args.length > 0) {

filename= args[0];

}

PersistentTime time= null;

FileInputStream fis= null;

ObjectInputStream in= null;try{

fis= newFileInputStream(filename);

in= newObjectInputStream(fis);

time=(PersistentTime) in.readObject();

in.close();

}catch(IOException ex) {

ex.printStackTrace();

}catch(ClassNotFoundException ex) {

ex.printStackTrace();

}//print out restored time

System.out.println("Flattened time: " +time.getTime());

System.out.println();//print out the current time

System.out.println("Current time: " +Calendar.getInstance().getTime());

}

}

View Code

注意:

1、持久化的对象必现实现Serializable接口或继承的父类实现了。

2、不能(例如系统级别的类Thread、OutPutStream)或不想被序列化的字段必需加transient声明。

transient是字段的修饰符,当一个字段声明为transient时,它就不能被序列化。

transient不能声明方法、类、接口,它们不需要被序列化。

2、自定义默认协议

由于类的构造函数只要在对象创建时候才调用,而反序列化的对象是用readObject创建的,不会再去调构造函数。如果构造函数里有执行某些行为,那么反序列化回来的对象就会丢失这些行为。

解决方法:增加两个方法,在保证序列化的默认行为后,增加自己要的行为。

private void writeObject(ObjectOutputStream out) throwsIOException;private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

例子:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

importjava.io.IOException;importjava.io.ObjectInputStream;importjava.io.ObjectOutputStream;importjava.io.Serializable;public class PersistentAnimation implementsSerializable, Runnable {private static final long serialVersionUID = 2850527457134768151L;transient privateThread animator;private intanimationSpeed;public PersistentAnimation(intanimationSpeed) {this.animationSpeed =animationSpeed;

startAnimation();

}public voidrun() {while (true) {//do animation here

}

}private void writeObject(ObjectOutputStream out) throwsIOException {

out.defaultWriteObject();

}private void readObject(ObjectInputStream in) throwsIOException, ClassNotFoundException {//our "pseudo-constructor"

in.defaultReadObject();//now we are a "live" object again, so let's run rebuild and start

startAnimation();

}private voidstartAnimation() {

animator= new Thread(this);

animator.start();

}

}

View Code

同理,如果父类已经实现Serializable接口,子类又不想被序列化,就可以添加这两个内容为空的方法。

3、自定义协议

实现Externalizable接口,复写writeExternal、readExternal两个方法,自己定义序列化协议(例如pdf的存取)。

public void writeExternal(ObjectOutput out) throwsIOException;public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;

序列化的陷阱

1、缓存流中的对象,再修改对象状态再写入是无效的。

ObjectOutputStream out = newObjectOutputStream(...);

MyObject obj= new MyObject(); //must be Serializable

obj.setState(100);

out.writeObject(obj);//saves object with state = 100

obj.setState(200);

out.writeObject(obj);//does not save new object state

2、版本控制

当你序列化一个对象存储到文件后,修改类的定义(例如增加个字段),当你反序列化时,会报一个java.io.InvalidClassException的异常。这是因为所有可以持续化的类都会有一个唯一的标识符,如果类的标识符跟反序列化对象的标识符不一样时,就会报这个异常。

解决方法:增加一个serialVersionUID字段作为类的标识符,只要标识符不变,就可反序列化。

添加方法:在eclipse中,鼠标悬浮到类名上,就可以看到“添加已生成的串行版本标识”,点击即可添加serialVersionUID。

3、性能问题

序列化对象写入文件的性能会比自己手动写入文件低。

参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值