Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会 比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java对象序 列化就能够帮助我们实现该功能。
使用Java对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的"状态",即它的成员变量。由此可知,对象序列化不会关注类中的静态变量。
我们可以使用java的IO流中的对象流ObjectOutputStream和ObjectInputStream来实现序列化和反序列化的操作。
java对象序列化就是将对象转换为字节流,然后可以通过这些值再生成相同状态的对象。对象序列化是对象持久化的一种实现方法,它是将一个对象的属性和方法转化为一种序列化的格式以用于存储和传输,反序列化就是根据这些保存的信息重建对象的过程。
序列化的实现:将需要被序列化的类实现Serializable接口,然后使用一个输出(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。所以使用ObjectOutputStream类实现序列化,ObjectInputStream类实现反序列化。
首先定义一个Person类,并实现Serializable接口:
public class Person implements Serializable { public String name; public int age; public Person(String name,int age){ this.name=name; this.age=age; } @Override public String toString() { return "person [name=" + name + ", age=" + age + "]"; } }
上面代码来看我们没有实现任何Serializable接口的方法,其实Serializable接口是一个标记接口,用于启动其序列化功能,此接口没有定义任何方法,只是作为一个标记。如图
1.ObjectOutputStream实现序列化
示例代码
public static void main(String[] args) { try { //序列化文件輸出流 OutputStream outputStream=new FileOutputStream("L:\\myfile.tmp"); //构建缓冲流 BufferedOutputStream buf=new BufferedOutputStream(outputStream); //构建字符输出的对象流 ObjectOutputStream obj=new ObjectOutputStream(buf); //序列化数据写入 obj.writeUTF("好好学习,天天向上");//字符串 obj.writeInt(18);//int类型 obj.writeObject(new Person("小明", 21));//Person对象 //关闭流 obj.close(); buf.close(); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
运行结果:
数据已经被序列化,无法正常显示出来。这个tmp的文件格式在我们很多应用程序中都可以看到。比如qq等,那怎么知道我们有没有序列化成功呢,我们来反序列化看看。
2.ObjectInputStream实现反序列化
示例代码:
public static void main(String[] args) { try { InputStream inputStream=new FileInputStream("L:\\myfile.tmp"); //构建缓冲流 BufferedInputStream buf=new BufferedInputStream(inputStream); //构建字符输入的对象流 ObjectInputStream obj=new ObjectInputStream(buf); //数据读取--只能按存入的顺序读取 String info=obj.readUTF(); int ok=obj.readInt(); Person tempPerson=(Person)obj.readObject(); System.out.println("str: "+info+"\n"+"整数为:"+ok+"\n"+"Person对象为:"+tempPerson); //关闭流 obj.close(); buf.close(); inputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
运行结果:
切记:读取的顺序要和写入的顺序一样,不然会读取出错,如把String info=obj.readUTF();和int ok=obj.readInt();换个位置就会出错
3.序列化一组对象
上面的读取只能按照顺序读取,如果我们不知道有多少和对象需要读取,那么将无法读取出来,为了解决这问题,可以使用序列化一组对象,然后在反序列这一组对象出来。反序列也必须按顺序来读取
如:序列化一组对象
public static void main(String[] args) { try { //序列化文件輸出流 OutputStream outputStream=new FileOutputStream("L:\\myfile.tmp"); //构建缓冲流 BufferedOutputStream buf=new BufferedOutputStream(outputStream); //构建字符输出的对象流 ObjectOutputStream obj=new ObjectOutputStream(buf); //序列化数据写入 obj.writeInt(18);//int类型 Person []persons={new Person("小明", 21),new Person("小黑", 20), new Person("小红", 22),new Person("小白", 18)}; obj.writeObject(persons);//一组Person对象 //关闭流 obj.close(); buf.close(); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
读取一组序列化,也要按顺序读取,要先读取int
public static void main(String[] args) { try { InputStream inputStream = new FileInputStream("L:\\myfile.tmp"); // 构建缓冲流 BufferedInputStream buf = new BufferedInputStream(inputStream); // 构建字符输入的对象流 ObjectInputStream obj = new ObjectInputStream(buf); // 数据读取--只能按存入的顺序读取 int ok = obj.readInt(); Person []tempPerson = (Person[]) obj.readObject(); System.out.println("整数为:" + ok ); for(int i=0;i<tempPerson.length;i++) System.out.println(tempPerson[i]); // 关闭流 obj.close(); buf.close(); inputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
运行结果:
4.关键字:transient
如果把Person的age属性前面加上关键字transient,则Person的age属性将不会被序列化。即如果用transient声明一个变量,当对象存储时,它的值不需要维持。
代码还是使用序列化和反序列化一组对象的代码,只是在Person类的age属性前加上关键字transient
运行结果:
相关推荐
ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。 2.输出字节流OutputStream IO 中输出字节流的继承图可见上图,可以看出: OutputStream 是所有的输出字节流的父类,它是一个...
JavaIO对象流 FileInputStream 与 ObjectInputStream 和 ObjectOutputStream 的组合 奥利弗·缪尔
ObjectInputStream ObjectOutputStream ByteArrayInputStream ByteArrayOutputStream 【字符流】 Reader Writer InputStreamReader OutputStreamWriter BufferedReader BufferedWriter /PrintWriter FileReader ...
java.io包中,提供了ObjectInputStream和ObjectOutputStream将数据流功能扩展至可读写对象。在ObjectInputStream中用readObject()方法可以直接读取一个对象,ObjectOutputStream中用writeObject()方法可以直接将对象...
|--ObjectOutputStream/:将java对象的基本数据类型和图形写入到OutputStream。 | |--PipedOutputStream/:可以将管道输出流连接到管道输入流来创建通信管道。 | 用方法connect(PipedInputStream snk) 将此管道...
我自己写的一些关于IO中的见解,可以用来参考。 File的增、删、改、查,FileReader和FileWriter类,BufferedReader和BufferedWriter类,ObjectOutputStream和ObjectInputStream类
其中包括以下接口和类: java.io.Serializable java.io.Externalizable ObjectOutput ObjectInput ObjectOutputStream ObjectInputStream Java高级程序设计实战教程第五章-Java序列化机制全文共15页,当前为第7页。...
java IO 字节流练习代码 FileInputStream和FileOutputStream BufferedInputStream 和 BufferedOutputStream DataInputStream 和 ...ObjectInputStream和ObjectOutputStream PrintStream PushbackInputStream
ObjectInputStream ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。 ObjectInputStream.GetField 提供对从输入流读取的持久字段的访问权限。 ObjectOutputStream ...
import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java....
import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; public class StuC { ArrayList <Student> al=new ArrayList();//类型ArrayList是集合,在定义ArrayList类型...
groovy-io消除了使用ObjectInputStream / ObjectOutputStream序列化对象的需要,而使用了JSON格式。 有第三个可选类( JsonObject ),请参见下面的“非类型化用法”。 groovy-io不需要类实现Serializable或...
文章目录1.IO流分析2.常用的IO流3....拷贝目录练习(重点)13.ObjectInputStream和ObjectOutputStream对象流14.IO +Properties联合使用 1.IO流分析 什么是IO? I:Input O:Output 通过IO可以完成对硬盘的读
4.java.io包中的objectinputstream和objectoutputstream类主要用于对对象(Object)的读写。 5.android 中service的实现方法是:startservice和bindservice。 6.activity一般会重载7个方法用来维护其生命周期,除了...
简洁分类 代码直接使用 InputStream OutputStream Reader Writer FileInputStream FileOutputStream FileReader FileWriter InputStreamReader ...ObjectOutputStream ObjectInputStream Scanner
import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; import java.io.EOFException; import java.net.ServerSocket; import java.net.Socket; import java.awt....
2.IO流简介 3.流的分类 输入流、输出流 字节流、字符流 节点流、包装流 4.字节流 InputStream:FileInputStream、ByteArrayInputStream、ObjectInputStream OutputStream:FileOutputStream、...
(1)用java写的RPC调用的demo。...(2)没有用到其他的jar包,java对象和流之间的转换用的是java.io.ObjectInputStream和java.io.ObjectOutputStream。 (3)下载解压,可以直接导入Eclipse运行调试。
ObjectInputStream和ObjectOutputStream 158 PrintStream 158 Reader 158 Writer 159 FileReader和FileWriter 159 BufferReader和BufferWriter 159 InputStreamReader和OutputStreamWriter 161 JAVA对象的序列化和反...