java 对象序列化和反序列化的性能,java中的序列化与反序列化
如何解决写爬虫IP受阻的问题?立即使用。
对象的序列化和反序列化
1)对象序列化是将对象转换成字节序列,反之亦然,称为对象反序列化。
2)序列化流(ObjectOutputStream),这是字节过滤流的—— writeObject()方法。
反序列化stream(objectinputstream)3354 read object()方法
3)可串行化接口(Serializable)
对象必须先实现序列化接口,然后才能序列化,否则将发生异常。
注:这个接口,没有任何方法,只是一个【标准】
一、最基本的序列化和反序列过程
序列化和反序列化都是由Object对象操作的。这里用一个简单的案例来演示对象序列化和反序列化的过程。
1、新建一个Student类(测试类)
注意:序列化需要一个实现序列化接口的类!
@SuppressWarnings(serial )
公共类学生实现Serializable{
私弦stuno//id
私弦stuna//名称
私立学校;//年龄
公共字符串getStuno() {
返回stuno
}
public void setStuno(String stuno){
this.stuno=stuno
}
公共字符串getStuna() {
返回stuna
}
public void setStuna(String stuna){
this.stuna=stuna
}
公共学生(){
super();
//TODO自动生成的构造函数存根
}
public Student(String stuno,String stuna,int stuage) {
super();
this.stuno=stuno
this.stuna=stuna
this . stu age=stu age;
}
@覆盖
公共字符串toString() {
return Student [stuno= stuno ,stuna= stuna ,stu age= stu age ];
}
public int getStuage() {
返程;
}
public void setStuage(int stuage){
this . stu age=stu age;
}
}2、将Student类的实例序列化成文件
基本操作步骤如下:
1),指定序列化保存的文件。
2)构造ObjectOutputStream类
3)构建学生班级。
4)使用writeObject方法的序列化
5)使用close()方法关闭流。
string file= demo/obj . dat ;
//对象的序列化
object output stream OOS=new object output stream(
new file output stream(file));
//保存学生对象,这是对象的序列化。
学生stu=新生( 01 ,迈克,18);
//使用writeObject方法序列化
OOS . writeobject(stu);
OOS . close();运行:可以看到在demo目录下生成了obj.dat的序列化文件。
3、将文件反序列化读出Student类对象
基本操作步骤如下:
1),指定反序列化的文件。
2)构造ObjectInputStream类
3)使用readObject方法反序列化
1)使用close方法关闭流。
string file= demo/obj . dat ;
ObjectInputStream ois=新的ObjectInputStream(
new file inputstream(file));
//用readObject()方法序列化
学生stu=(学生)ois . read object();//strong制类型转换
system . out . println(stu);
ois . close();运行结果:
注意:当文件被反序列化时,默认情况下,readObject方法检索的所有对象都是Object类型,并且必须转换为相应的类型。
二、transient及ArrayList源码分析
在日常编程过程中,我们有时不希望一个类的所有元素都被编译器序列化。那我们该怎么办?
Java提供了一个transient关键字来修饰我们不希望被jvm自动序列化的元素。先简单解释一下这个关键词。
transient 关键字:被transient修饰的元素,该元素不会进行jvm默认的序列化,但可以自己完成这个元素的序列化。
注意:
1)在以后的网络编程中,如果有一些不需要传输的元素,可以用transient来修饰,节省流量;序列化有效元素以提高性能。
2)可以自己使用writeObject来序列化这个元素。
ArrayList使用此方法来优化操作。ArrayList的核心容器Object[] elementData是用transient修饰的,但它的数组本身是在writeObject中序列化的。仅序列化数组中的有效元素。阅读是相似的。
--------------自己序列化的方式---------------
向要序列化的类中添加两个方法(这两个方法是从ArrayList源代码中提取的,是两个特殊的方法):
private void writeObject(Java . io . object output stream s)抛出java.io.IOException{
s . defaultwriteobject();//序列化jvm默认情况下可以序列化的元素
s . write int(stu age);//自己完成transient修饰的元素的序列化
}
私有void read object(Java . io . objectinputstream s)抛出java.io.IOException,ClassNotFoundException{
s . default read object();//反序列化jvm默认情况下可以反序列化的元素
this . stu age=s . readint();//自己完成stuage的反序列化
}添加这两个方法后,即使是transient修饰的元素也可以像刚才一样进行序列化和反序列化,jvm会自动使用这两个方法来帮助我们完成这个动作。
还有一个问题。为什么需要手动完成序列化和反序列化?有什么意义?
这个问题还得从ArrayList的源代码来分析:
可以看出,ArrayList源代码中自序列化的目的是,ArrayList的底层是一个数组。自序列化可以过滤数组中的无效元素,只序列化数组中的有效元素,从而提高性能。
因此,在实际编程过程中,我们可以根据需要自行完成序列化,以提高性能。
三、序列化中子父类构造函数问题
在一个类的序列化和反序列化中,如果子类和父类有关系,那么序列化和反序列化的过程是怎样的?
这里我写一个测试类,测试子类和父类实现序列化和反序列化时构造函数的实现变化。
公共静态void main(String[] args)引发IOException {
//TODO自动生成的方法存根
string file= demo/foo . dat ;
object output stream OOS=new object output stream(
new file output stream(file));
foo 2 foo 2=new foo 2();
OOS . writeobject(foo 2);
OOS . flush();
OOS . close();
}
}
类Foo实现Serializable{
公共Foo(){
system . out . println( foo );
}
}
类Foo1扩展了Foo{
公共Foo1(){
system . out . println( foo 1 );
}
}
Foo2类扩展了Foo1{
公共Foo2(){
system . out . println( foo 2 );
}
}运行结果:这是序列化过程中递归调用父类的构造函数。
我们来看看反序列化时是否递归调用了父类的构造函数。
ObjectInputStream ois=新的ObjectInputStream(
new file inputstream(file));
foo 2 foo 2=(foo 2)ois . read object();
ois . close();运行:控制台没有输出。
那么这个结果是否证明了在反序列化过程中,从来不调用父类的构造函数呢?
但是,无法证明!
因为看下面不同的测试例子:
类别栏{
公共酒吧(){
system . out . println( bar );
}
}
Bar1类扩展Bar实现Serializable{
公共栏1(){
system . out . println( bar 1 );
}
}
Bar2类扩展了Bar1{
公共栏2(){
system . out . println( bar 2 );
}
}我们用这个例子来测试序列化和反序列化。
序列化结果:
反序列化结果:显示未实现序列化接口的父类调用构造函数。
【反序列化时】,递归调用构造函数up将从【可序列化的一级父类】开始结束。也就是说,谁实现了可序列化性(包括继承的实现),谁就不会调用它的构造函数。
总结:
1)父类实现serializable接口,子类继承可以序列化。
当子类反序列化时,父类实现序列化接口,因此不会递归调用其构造函数。
2)父类不实现serializable接口,子类可以自己实现serializable。
当子类被反序列化时,如果父类没有实现序列化接口,它的构造函数将被递归调用。
本文来自java入门专栏,欢迎学习!这就是Java对象的序列化和反序列化的细节。请多关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。