A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小飞龙 于 2012-6-21 22:20 编辑

ObjectInputStream与ObjectOutputStream这两个类看了半天的视频也不明白,它具体是什么时候用,和其他流有什么区别?怎么去理解ObjectInputStream与ObjectOutputStream与其他流的关系?

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 新手鼓励一个~~

查看全部评分

7 个回复

倒序浏览
对象流 ObjectInputStream和ObjectOutputStream
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
注意:在自定义类中静态static 成员不会被序列化也就是不会被持久存储,如果想把非静态成员也不被序列化时可以在成员前加一个修饰符:transient;还可在类中自定义UID号:static final long serialVersionUID = 42L(UID号);

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

ObjectInputStream 确保从流创建的图形中所有对象的类型与 Java 虚拟机中显示的类相匹配。使用标准机制按需加载类。

只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。

readObject 方法用于从流读取对象。应该使用 Java 的安全强制转换来获取所需的类型。在 Java 中,字符串和数组都是对象,所以在序列化期间将其视为对象。读取时,需要将其强制转换为期望的类型。

可以使用 DataInput 上的适当方法从流读取基本数据类型。

默认情况下,对象的反序列化机制会将每个字段的内容恢复为写入时它所具有的值和类型。反序列化进程将忽略声明为瞬态或静态的字段。对其他对象的引用使得根据需要从流中读取这些对象。使用引用共享机制能够正确地恢复对象的图形。反序列化时始终分配新对象,这样可以避免现有对象被重写。

读取对象类似于运行新对象的构造方法。为对象分配内存并将其初始化为零 (NULL)。为不可序列化类调用无参数构造方法,然后从以最接近 java.lang.object 的可序列化类开始和以对象的最特定类结束的流恢复可序列化类的字段。

例如,要从由 ObjectOutputStream 中的示例写入的流读取:


        FileInputStream fis = new FileInputStream("t.tmp");
        ObjectInputStream ois = new ObjectInputStream(fis);

        int i = ois.readInt();
        String today = (String) ois.readObject();
        Date date = (Date) ois.readObject();

        ois.close();
类控制实现 java.io.Serializable 或 java.io.Externalizable 接口时的序列化方式。

实现 Serializable 接口允许对象序列化,以保存和恢复对象的全部状态,并且允许类在写入流时的状态和从流读取时的状态之间变化。它自动遍历对象之间的引用,保存和恢复全部图形。

在序列化和反序列化进程中需要特殊处理的 Serializable 类应该实现以下方法:


private void writeObject(java.io.ObjectOutputStream stream)
     throws IOException;
private void readObject(java.io.ObjectInputStream stream)
     throws IOException, ClassNotFoundException;
private void readObjectNoData()
     throws ObjectStreamException;
readObject 方法负责使用通过对应的 writeObject 方法写入流的数据,为特定类读取和恢复对象的状态。该方法本身的状态,不管是属于其超类还是属于其子类,都没有关系。恢复状态的方法是,从个别字段的 ObjectInputStream 读取数据并将其分配给对象的适当字段。DataInput 支持读取基本数据类型。

尝试读取由对应的 writeObject 方法写入的超出自定义数据边界的对象数据将导致抛出 OptionalDataException(eof 字段值为 true)。超出已分配数据末尾的非对象读取以指示流末尾的方式反映数据结束:按位读取与字节读取或字节数读取一样,将返回 -1,基元读取将抛出 EOFException。如果不存在对应的 writeObject 方法,则默认的序列化数据的末尾标记已分配数据的末尾。

从 readExternal 方法发出的基元和对象读取调用的行为方式一样:如果流已经定位在由相应 writeExternal 方法写入的数据末尾,则对象读取将抛出 OptionalDataException(其 eof 设置为 true),按位读取将返回 -1,基元读取将抛出 EOFException。注意,此行为不适用于使用旧 ObjectStreamConstants.PROTOCOL_VERSION_1 协议写入的流,在这些流中,没有划分出由 writeExternal 方法写入的数据末尾,因此无法检测。

如果序列化流没有将给定类列为要反序列化的对象的超类,则 readObjectNoData 方法负责初始化其特定类的对象状态。在接收方使用的反序列化实例类的版本不同于发送方,并且接收者版本扩展的类不是发送者版本扩展的类时,此事可能发生。如果序列化流已经被篡改,也会发生这种情况;因此,不管源流是“敌意的”还是不完整的,readObjectNoData 方法都可以用来正确地初始化反序列化的对象。

对于没有实现 java.io.Serializable 接口的任何对象,序列化不会对其字段进行读取或赋值。非 serializable 的 Object 的子类可以为 serializable。在此情况下,非 serializable 类必须具有无参数的构造方法以允许其字段能被初始化。在此情况下,子类负责保存和恢复非 serializable 类的状态。经常出现的情况是,该类的字段是可访问的(public、package 或 protected),或者存在可用于恢复状态的 get 和 set 方法。

反序列化对象进程中发生的所有异常将由 ObjectInputStream 捕获并将中止读取进程。

实现 Externalizable 接口允许对象假定可以完全控制对象的序列化形式的内容和格式。调用 Externalizable 接口的方法(writeExternal 和 readExternal)来保存和恢复对象状态。当这两种方法被某个类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法读写其本身的状态。对象负责处理出现的任何版本控制。

Enum 常量的反序列化不同于普通的 serializable 或 externalizable 对象。Enum 常量的序列化形式只包含其名称;不传送常量的字段值。要反序列化 enum 常量,ObjectInputStream 需要从流中读取常量的名称;然后将 enum 常量的基本类型和接收到的常量名称作为参数,调用静态方法 Enum.valueOf(Class, String) 获取反序列化的常量。与其他 serializable 或 externalizable 对象一样,enum 常量可以作为序列化流中随后出现的反向引用的目标。不可以自定义 enum 常量的反序列化进程:在反序列化期间,enum 类型所定义的任何与类有关的 readObject、readObjectNoData 和 readResolve 方法都将被忽略。类似地,任何 serialPersistentFields 或 serialVersionUID 字段声明也将被忽略(所有 enum 类型都有一个固定的 0L 的 serialVersionUID)。

回复 使用道具 举报
下面是引用hongbo同学的总结。

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久性存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。
ObjectInputStream 确保从流创建的图形中所有对象的类型与 Java 虚拟机中的显示的类相匹配。使用标准机制按需加载类。

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
Java中ObjectInputStream 与 ObjectOutputStream这两个包装类可用于输入流中读取对象类数据和将对象类型的数据写入到底层输入流 。ObjectInputStream 与 ObjectOutputStream 类所读写的对象必须实现了 Serializable 接口。
回复 使用道具 举报
简单理解就是
ObjectInputStream与ObjectOutputStream 意义在于与FileInputStream 和  FileOutputStream 配合使用可以为应用程序提供对对象图形的持久性存储......
简单讲就是和序列化反序列化一个道理.不要钻的太深, 用的时候直接调用生成的文件.完成持久化存储
API文档介绍得很清楚

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久性存储......
API文档介绍得很清楚,建议楼主好好看看

import java.io.*;
class  CopyPic
{
         public static void main(String[] args)
        {
                 FileOutputStream fos = null;
                 FileInputStream fis = null;//FileOutputStream它以本地文件系统作为输入流起点, 与其他与文件有关的类配合可以对文件进行读写操作
                 try
                 {
                         fos = new FileOutputStream("c:\\2.bmp");//用字节写入流对象创建一个图片文件。用于存储获取到的图片数据
                         fis = new FileInputStream("c:\\1.bmp");//用字节读取流对象和图片关联

                        byte[] buf = new byte[1024];

                        int len = 0;

                        while((len=fis.read(buf))!=-1)//通过循环读写,完成数据的存储
                         {
                                 fos.write(buf,0,len);
                         }
                 }
                 catch (IOException e)
                 {
                         throw new RuntimeException("复制文件失败");
                 }
                 finally
                 {
                         try
                         {
                                 if(fis!=null)
                                         fis.close();
                         }
                         catch (IOException e)
                         {
                                 throw new RuntimeException("读取关闭失败");
                         }
                         try
                         {
                                 if(fos!=null)
                                         fos.close();
                         }
                         catch (IOException e)
                         {
                                 throw new RuntimeException("写入关闭失败");
                         }
                 }
         }
}
回复 使用道具 举报
刘笑 中级黑马 2012-6-21 22:11:12
8#
ObjectOutputStream 和 ObjectInputStream 分别利用 FileOutputStream 和 FileInputStream 能支持应用程序实现对象图象的稳定存储。

ObjectInputStream 可用于恢复以前序列化过的对象。另外其它一些情况也使用此类,诸如使用一个 Socket 在主机间传递对象时,

或在远程通讯系统中为实现参数和参变量的通讯而进行对象传递时。

ObjectInputStream 保证从流中创建的图象中的所有对象的类型与 Java 虚拟机中出现的类匹配。使用标准机制按需装载相应类
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马