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/ObjectOutputStream):用于序列化和反序列化Java对象。 2. 字符流: - 字符输入流(Reader):如FileReader,用于读取字符数据,通常用于处理文本文件。 - 字符输出流(Writer):...
IO流还包括输入流(Input Stream)、输出流(Output Stream)、缓冲流(Buffered Stream)、转换流(Converter Stream)以及对象流(Object Stream)等子类,它们各自有不同的功能和应用场景。例如,FileInputStream...
Java还提供了一种特殊的流,即对象流,用于对象的序列化和反序列化。`ObjectOutputStream`用于写入对象到流中,`ObjectInputStream`则用于从流中读取对象。 七、文件操作练习 在你给出的"demo17"和"task09"这两个...
- ObjectInputStream和ObjectOutputStream允许我们将Java对象序列化和反序列化,从而实现对象的持久化存储或网络传输。 5. 复用流: - PipedInputStream和PipedOutputStream用于线程间通信,一个线程写入数据,另...
本知识点将深入探讨Java IO流的相关细节,包括节点流与处理流的概念,以及文件流、标准输入输出流、缓冲流、转换流、打印流、数据流和对象流的处理过程和使用方法。 首先,Java中的IO流根据数据流向可以分为输入流...
5. **对象序列化流** - `ObjectInputStream` 和 `ObjectOutputStream`: 用于对象的序列化和反序列化。 6. **字节流** - `InputStream`: 输入流基类。 - `FileInputStream`: 用于读取文件中的字节。 - `...
总的来说,Java IO流是一个强大的工具集,它涵盖了各种数据源和目标的输入输出操作,从简单的文件读写到复杂的网络通信和对象序列化。理解并熟练运用Java IO流是成为一名合格的Java开发者的必备技能之一。通过深入...
Java提供了许多不同的流类来适应各种特定需求,例如FileInputStream和FileOutputStream用于文件操作,BufferedReader和BufferedWriter用于缓冲数据,DataInputStream和DataOutputStream支持基本类型的数据读写,...
- ObjectInputStream和ObjectOutputStream实现了Java对象的序列化和反序列化,使得对象可以存储到磁盘或通过网络传输。 六、文件操作与目录操作 - File类提供了文件和目录的基本操作,如创建、删除、重命名等。 - ...
4. 对象流(Object Stream):用于序列化和反序列化对象,包括ObjectInputStream和ObjectOutputStream。 5. 文件流(File Stream):专用于文件读写的流,如FileInputStream和FileOutputStream。 6. 缓冲流...
在文件上传下载场景中,如果需要传输的对象实现了`Serializable`接口,就可以使用ObjectInputStream和ObjectOutputStream进行序列化和反序列化操作。 `TestBufferedReaderWriter.java`涉及到了缓冲流...
`ObjectOutputStream`和`ObjectInputStream`用于实现这一过程。 5. **过滤流(Filter Stream)**: - 过滤流不直接与数据源交互,而是包裹在其他流之上,提供额外的功能,如数据的压缩、解压缩、编码转换等。 6. ...
6. 对象流(ObjectInputStream和ObjectOutputStream): 这两种流允许序列化和反序列化Java对象,使得对象能够在不同程序之间传输或持久化存储。 7. 文件流(FileInputStream和FileOutputStream): 文件输入流和...
Java提供了ObjectInputStream和ObjectOutputStream,支持对象的序列化和反序列化。序列化是将对象转化为字节流,便于存储或网络传输;反序列化则是将字节流恢复为原来的对象。 六、PPT教学文档 PPT教学文档通常会...
BufferedReader/BufferedWriter(缓冲字符流),DataInputStream/DataOutputStream(处理基本类型数据),ObjectInputStream/ObjectOutputStream(处理对象序列化)。 4. 工作模板: 在实际工作中,IO流的使用通常...
- **ObjectInputStream** 和 **ObjectOutputStream**:用于序列化和反序列化Java对象,实现对象的持久化存储。 2. 字符流: - **Reader** 和 **Writer**:这是所有字符输入流和输出流的基类,用于处理Unicode字符...
- **ObjectInputStream/ObjectOutputStream**:支持序列化,允许程序将对象写入流和从流中恢复对象。 5. **多路复用流**: - **PipedReader/PipedWriter**:用于线程间的通信,一个线程写入,另一个线程读取。 -...
4. **对象流**: - Java的序列化和反序列化操作涉及到`ObjectInputStream`和`ObjectOutputStream`,它们可以将Java对象转换成字节流,便于存储或在网络上传输。 5. **过滤流**: - 过滤流是带有额外功能的流,...
3. 对象序列化与反序列化:ObjectInputStream和ObjectOutputStream允许我们将Java对象写入流中,然后在其他地方读取出来,实现对象的持久化。 4. 转换流(Stream Bridge):InputStreamReader和OutputStreamWriter...
3. **对象流**:如ObjectInputStream和ObjectOutputStream,用于序列化和反序列化对象。 4. **过滤流**:如BufferedInputStream,允许添加额外的功能,如数据压缩、加密等。 5. **管道流**:如PipedInputStream和...