Java IO _对象序列化

1、掌握对象序列化的作用
2、掌握Serializable 接口的作用
3、可以使用ObjectOutputStream 进行对象序列化操作
4、可以使用ObjectInputStream 进行对象的反序列化操作
5、掌握Externalizable 接口的作用及与Serializable 接口的实现区别
6、掌握transient 关键字的作用
7、可以序列化一组对象

1、什么对象序列化
一个对象产生之后实际上是在内存中为其开辟了一个在存储空间,方便存储信息。

一个类不能平白无故的被序列化。
但是,在此接口中没有任何一个方法,此接口属于一个标识接口,表示具备了某种能力。
例如:现在定义一个类,此类可以被序列化
定义可序列化的类
[java] view plain copy
  1. importjava.io.Serializable;
  2. publicclassPersonimplementsSerializable{
  3. privateStringname;//声明name属性,但是此属性不被序列化
  4. privateintage;//声明age属性
  5. publicPerson(Stringname,intage){//通过构造设置内容
  6. this.name=name;
  7. this.age=age;
  8. }
  9. publicStringtoString(){//覆写toString()方法
  10. return"姓名:"+this.name+";年龄:"+this.age;
  11. }
  12. };
以后此类的对象,就可以被序列化了。变为二进制byte 流。



但是在进行序列化或反序列化操作的时候,对于不同的 JDK 版本,实际上会出现版本的兼容问题。
[java] view plain copy
  1. importjava.io.Serializable;
  2. publicclassPersonimplementsSerializable{
  3. privatestaticfinallongserialVersionUID=1l;
  4. privateStringname;//声明name属性,但是此属性不被序列化
  5. privateintage;//声明age属性
  6. publicPerson(Stringname,intage){//通过构造设置内容
  7. this.name=name;
  8. this.age=age;
  9. }
  10. publicStringtoString(){//覆写toString()方法
  11. return"姓名:"+this.name+";年龄:"+this.age;
  12. }
  13. };

private static final long serialVersionUID = 1l;

如果使用开发工具开发 ,没有编写此代码,则会出现一些安全警告的信息。

2、对象的序列化及反序列化操作
对象序列化依靠ObjectOutputStream 对象反序列化依靠ObjectInputStream.
2.1 序列化:ObjectOutStream

[java] view plain copy
  1. importjava.io.File;
  2. importjava.io.FileOutputStream;
  3. importjava.io.OutputStream;
  4. importjava.io.ObjectOutputStream;
  5. publicclassSerDemo01{
  6. publicstaticvoidmain(Stringargs[])throwsException{
  7. Filef=newFile("D:"+File.separator+"test.txt");//定义保存路径
  8. ObjectOutputStreamoos=null;//声明对象输出流
  9. OutputStreamout=newFileOutputStream(f);//文件输出流
  10. oos=newObjectOutputStream(out);
  11. oos.writeObject(newPerson("张三",30));//保存对象
  12. oos.close();//关闭
  13. }
  14. };
到底序列化了那些东西呢?
所有的对象拥有各自的属性值,但是所有的方法都是公共的,所以序列化对象的时候实际上序列化的就是属性。
2.2 反序列化:ObjectInputStream

[java] view plain copy
  1. importjava.io.File;
  2. importjava.io.FileInputStream;
  3. importjava.io.InputStream;
  4. importjava.io.ObjectInputStream;
  5. publicclassSerDemo02{
  6. publicstaticvoidmain(Stringargs[])throwsException{
  7. Filef=newFile("D:"+File.separator+"test.txt");//定义保存路径
  8. ObjectInputStreamois=null;//声明对象输入流
  9. InputStreaminput=newFileInputStream(f);//文件输入流
  10. ois=newObjectInputStream(input);//实例化对象输入流
  11. Objectobj=ois.readObject();//读取对象
  12. ois.close();//关闭
  13. System.out.println(obj);
  14. }
  15. };
问题:
如果一个类实现了Serializable 接口,则肯定此类可以被序列化下来,那么也就意味着此类多了一项功能,可以被序列化,那么让所有的类都实现此接口是不是更好啊?
因为JDK是会不断升级的,现在Serializable 接口中没有任何定义,那么以后呢?
3、Externalizable 接口
使用Serilizable 接口可以方便的序列化一个对象,但是在序列化操作中也提供了另外一种序列化机制——Externalizable 接口。

定义:
public interface Externalizable
extends Serializable
方法:
写入:void writeExternal(ObjectOutput out)throws IOException
读取:void readExternal(ObjectInput in)throws IOException,ClassNotFoundException
利用此接口修改之前的程序
[java] view plain copy
  1. importjava.io.Externalizable;
  2. publicclassPersonimplementsExternalizable{
  3. privatestaticfinallongserialVersionUID=1l;
  4. privateStringname;//声明name属性
  5. privateintage;//声明age属性
  6. publicPerson(Stringname,intage){//通过构造设置内容
  7. this.name=name;
  8. this.age=age;
  9. }
  10. publicStringtoString(){//覆写toString()方法
  11. return"姓名:"+this.name+";年龄:"+this.age;
  12. }
  13. publicvoidwriteExternal(ObjectOutputout)throwsIOException{
  14. out.writeObject(this.name);//保存姓名属性
  15. out.writeInt(this.age);//保age属性
  16. }
  17. publicvoidreadExternal(ObjectInputin)throwsIOException,ClassNotFoundException{
  18. this.name=in.readObject();//读取姓名
  19. this.age=in.readInt();//读取年龄
  20. }
  21. };
为了方便测试,现在将,现在序列化及反序列化操作形成方法调用的形式。
[java] view plain copy
  1. importjava.io.File;
  2. importjava.io.IOException;
  3. importjava.io.FileOutputStream;
  4. importjava.io.OutputStream;
  5. importjava.io.ObjectOutputStream;
  6. importjava.io.FileInputStream;
  7. importjava.io.InputStream;
  8. importjava.io.ObjectInputStream;
  9. publicclassSerDemo03{
  10. publicstaticvoidmain(Stringargs[])throwsException{
  11. //ser();
  12. dser();
  13. }
  14. publicstaticvoidser()throwsException{
  15. Filef=newFile("D:"+File.separator+"test.txt");//定义保存路径
  16. ObjectOutputStreamoos=null;//声明对象输出流
  17. OutputStreamout=newFileOutputStream(f);//文件输出流
  18. oos=newObjectOutputStream(out);
  19. oos.writeObject(newPerson("张三",30));//保存对象
  20. oos.close();//关闭
  21. }
  22. publicstaticvoiddser()throwsException{
  23. Filef=newFile("D:"+File.separator+"test.txt");//定义保存路径
  24. ObjectInputStreamois=null;//声明对象输入流
  25. InputStreaminput=newFileInputStream(f);//文件输入流
  26. ois=newObjectInputStream(input);//实例化对象输入流
  27. Objectobj=ois.readObject();//读取对象
  28. ois.close();//关闭
  29. System.out.println(obj);
  30. }
  31. };
以上程序执行的时候出现了一个错误:

在使用Externalizable 接口的时候需要在被序列化的类中定义一个无参构造,因为此接口在进行反序列化的时候,会先使用类中的无参构造方法为其进行实例化,之后再将内容分别设置到属性之中,修改Person 类:
[java] view plain copy
  1. importjava.io.Externalizable;
  2. importjava.io.*;
  3. publicclassPersonimplementsExternalizable{
  4. privatestaticfinallongserialVersionUID=1L;
  5. privateStringname;//声明name属性
  6. privateintage;//声明age属性
  7. publicPerson(){}//无参构造
  8. publicPerson(Stringname,intage){
  9. this.name=name;
  10. this.age=age;
  11. }
  12. publicStringtoString(){//覆写toString()方法
  13. return"姓名:"+this.name+":年龄:"+this.age;
  14. }
  15. publicvoidwriteExternal(ObjectOutputout)
  16. throwsIOException{
  17. out.writeObject(this.name);//保存姓名属性
  18. out.writeInt(this.age);//保存age属性
  19. }
  20. publicvoidreadExternal(ObjectInputin)
  21. throwsIOException,ClassNotFoundException{
  22. this.name=(String)in.readObject();//读取姓名
  23. this.age=in.readInt();//读取年龄
  24. }
  25. }

在开发中使用Serialzable 接口是最多的。而Externalizable 接口基本上是不会出现的。

在序列化操作的时候,如果某个属性不希望被序列化下来,则可以直接使用transient 关键字声明。
[java] view plain copy
  1. importjava.io.Serializable;
  2. publicclassPersonimplementsSerializable{
  3. privateStringname;//声明name属性,但是此属性不被序列化
  4. privateintage;//声明age属性
  5. publicPerson(Stringname,intage){//通过构造设置内容
  6. this.name=name;
  7. this.age=age;
  8. }
  9. publicStringtoString(){//覆写toString()方法
  10. return"姓名:"+this.name+";年龄:"+this.age;
  11. }
  12. };
操作代码:
[java] view plain copy
  1. importjava.io.File;
  2. importjava.io.IOException;
  3. importjava.io.FileOutputStream;
  4. importjava.io.OutputStream;
  5. importjava.io.ObjectOutputStream;
  6. importjava.io.FileInputStream;
  7. importjava.io.InputStream;
  8. importjava.io.ObjectInputStream;
  9. publicclassSerDemo04{
  10. publicstaticvoidmain(Stringargs[])throwsException{
  11. ser();
  12. dser();
  13. }
  14. publicstaticvoidser()throwsException{
  15. Filef=newFile("D:"+File.separator+"test.txt");//定义保存路径
  16. ObjectOutputStreamoos=null;//声明对象输出流
  17. OutputStreamout=newFileOutputStream(f);//文件输出流
  18. oos=newObjectOutputStream(out);
  19. oos.writeObject(newPerson("张三",30));//保存对象
  20. oos.close();//关闭
  21. }
  22. publicstaticvoiddser()throwsException{
  23. Filef=newFile("D:"+File.separator+"test.txt");//定义保存路径
  24. ObjectInputStreamois=null;//声明对象输入流
  25. InputStreaminput=newFileInputStream(f);//文件输入流
  26. ois=newObjectInputStream(input);//实例化对象输入流
  27. Objectobj=ois.readObject();//读取对象
  28. ois.close();//关闭
  29. System.out.println(obj);
  30. }
  31. };
transient + Serilizable 接口完全可以取代Externalizable 接口的功能。
5、序列化一组对象

如果要保存多个对象,则最好使用对象数组的形式完成。
[java] view plain copy
  1. importjava.io.File;
  2. importjava.io.IOException;
  3. importjava.io.FileOutputStream;
  4. importjava.io.OutputStream;
  5. importjava.io.ObjectOutputStream;
  6. importjava.io.FileInputStream;
  7. importjava.io.InputStream;
  8. importjava.io.ObjectInputStream;
  9. publicclassSerDemo05{
  10. publicstaticvoidmain(Stringargs[])throwsException{
  11. Personper[]={newPerson("张三",30),newPerson("李四",31),
  12. newPerson("王五",32)};
  13. ser(per);
  14. Objecto[]=(Object[])dser();
  15. for(inti=0;i<o.length;i++){
  16. Personp=(Person)o[i];
  17. System.out.println(p);
  18. }
  19. }
  20. publicstaticvoidser(Objectobj[])throwsException{
  21. Filef=newFile("D:"+File.separator+"test.txt");//定义保存路径
  22. ObjectOutputStreamoos=null;//声明对象输出流
  23. OutputStreamout=newFileOutputStream(f);//文件输出流
  24. oos=newObjectOutputStream(out);
  25. oos.writeObject(obj);//保存对象
  26. oos.close();//关闭
  27. }
  28. publicstaticObject[]dser()throwsException{
  29. Filef=newFile("D:"+File.separator+"test.txt");//定义保存路径
  30. ObjectInputStreamois=null;//声明对象输入流
  31. InputStreaminput=newFileInputStream(f);//文件输入流
  32. ois=newObjectInputStream(input);//实例化对象输入流
  33. Objectobj[]=(Object[])ois.readObject();//读取对象
  34. ois.close();//关闭
  35. returnobj;
  36. }
  37. };
问题:保存的数据有限,所以为了解决这样的问题,Java 中引入了类集 框架解决数组的存储限制问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值