java 序列化 transient_Java序列化和反序列化与transient关键字

当我们需要把Java对象保存在磁盘中或者要在网络中传播,那我们就要用到Java对象的序列化和反序列化。对象序列化把内存中的对象转换成跟平台无关的二进制流,从而可以永久的保存在磁盘中或者在网络中传播。这在现实开发中经常用到,如:web容器把Session保存在磁盘中,减少内存的占用,等需要时,再反序列化。还有分布部署程序时,我们用到的RPC远程访问别人方法返回对象时等等。

实现序列化

我们只要实现Serializable接口就行,当然Java已经帮我们封装好了实现类,所以Serializable接口是一个标记接口,我们不用实现任何方法,它就是用来表明这个类对象是可序列化的。如:

publicclassdogimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;//版本号,反序列化那里会说到

privateStringname;

privateStringage;

publicdog(Stringname,Stringage){

this.name=name;

this.age=age;

System.out.println("调用了构造方法");

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicStringgetAge(){

returnage;

}

publicvoidsetAge(Stringage){

this.age=age;

}

}

使用对象流实现序列化

1.创建一个ObjectOutputStream,这个是对象处理流,所以必须建立在其他文件流上(FileOutputStream)

ObjectOutputStreamoutputStream=newObjectOutputStream(newFileOutputStream("Object.txt"));

2.然后用ObjectOutputStream的writeObject(Object object)方法就可以输出序列化对象。

dog d=newdog("小狗","12");

outputStream.writeObject(d);

使用对象流实现反序列化

1.创建一个ObjectInputStream,这个是对象处理流,所以必须建立在其他文件流上(FileInputStream)

ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream(“Object.txt”));

2然后用创建一个ObjectInputStream的raadObject()方法就可以输入序列化对象

ObjectInputStreaminputStream=newObjectInputStream(newFileInputStream("Object.txt"));

dog dd=(dog)inputStream.readObject();

readObject返回的是Object,我们知道类型可以强制转换。

注意:由于我们读取到的是对象,所以我们必须要有java对象的class文件,而且我们知道dog类只有一个有参构造方法,这个构造方法里有输出语句,但是我们获得对象时,并没有输出,所以我们可以得出反序列化时,我们不用构造方法来初始化对象。

对象引用的序列化

当你要序列化的对象有(除了基本类型和String类型外)引用其他对象时,这个对象必须也是要序列化的。

publicclassCatimplementsSerializable{

privatedog d;

privateStringname;

publicCat(dog d,Stringname){

this.d=d;

this.name=name;

}

publicdog getD(){

returnd;

}

publicvoidsetD(dog d){

this.d=d;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

}

Cat类有一个dog对象,只有dog对象是可序列化的,Cat类对象才可以序列化,因为当你序列化Cat类对象时,由于dog对象不可序列化,所以在反序列化时为了正常返回Cat对象,要对dog对象进行反序列化,所以dog对象要是可序列化的。当然我们可以用transient关键字进行指定哪些不用序列化,后面会说到。

序列号

当你对同一个对象序列化多次,反序列化回来的多个对象怎么保证是同一个呢,所以就有了序列号。

ObjectOutputStreamoutputStream=newObjectOutputStream(newFileOutputStream("Object.txt"));

dog d=newdog("小狗","12");

outputStream.writeObject(d);

outputStream.writeObject(d);

我们对d这个对象序列化3次,正常每次序列化都会把d这对象写入到磁盘中,就有了3个d对象在磁盘中,当你反序列化时就有了3个不同的对象,于是Java引入了序列号。

所有保存到磁盘的对象都有一个序列号。

当程序序列号一个对象时,先查看这个对象是否序列号,只有没有序列化过的,系统才会把这个对象转换成字节序列化到磁盘中,或则直接输出序列号

1fb0e82b63b7f9fe004e138585d8c680.png

ObjectInputStreaminputStream=newObjectInputStream(newFileInputStream("Object.txt"));

dog d1=(dog)inputStream.readObject();

dog d2=(dog)inputStream.readObject();

System.out.println(d1==d2);

版本号

我们发现每个序列化的类都有这个 ,如果没有系统每次都会随机生成

private static final long serialVersionUID = 1L;

这个我们称为版本号,为了就是当你反序列化时,可以兼容。也就是说,当你的类升级后,只要这个编号不变,序列化机制就把它们当成同一个版本,这样,如果当一个类对象让你序列化后,你修改了这个类,保证改对象可以正常的被反序列化。如果你没有写,改变量由jvm更具类信息就行计算,所以修改后肯定不同,就不能正常的反序列化了。

transient关键字

这个关键字就是让序列化机制不用理会它修饰的变量,这个变量不会被序列化

publicclassdogimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

privateStringname;

privatetransientStringage;

publicdog(Stringname,Stringage){

this.name=name;

this.age=age;

System.out.println("调用了构造方法");

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicStringgetAge(){

returnage;

}

publicvoidsetAge(Stringage){

this.age=age;

}

}

测试

publicclasstest{

publicstaticvoidmain(Stringarg[])throwsException{

ObjectOutputStreamoutputStream=newObjectOutputStream(newFileOutputStream("Object.txt"));

dog d=newdog("小狗","12");

outputStream.writeObject(d);

ObjectInputStreaminputStream=newObjectInputStream(newFileInputStream("Object.txt"));

dog d1=(dog)inputStream.readObject();

System.out.println("name:"+d1.getName());

System.out.println("age:"+d1.getAge());

}

}

结果:

调用了构造方法

name:小狗

age:null

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值