Java 日看一类(39)之IO包中的ObjectStreamException和OptionalDataException异常类

本文介绍了ObjectStreamException及其子类OptionalDataException,详细解释了这两种异常的用途和应用场景,特别是OptionalDataException在序列化过程中遇到非预期数据时如何抛出。

ObjectStreamException异常类继承自IOException



该类的类头注释如下:

* Superclass of all exceptions specific to Object Stream classes.

大意如下:

描述所有对象流类异常的顶级类



该类含有如下的成员变量:

序列化ID

private static final long serialVersionUID = 7260898174833392607L;


该类含有如下的成员方法:

构造方法(传入出错的类名)

protected ObjectStreamException(String classname) {
    super(classname);
}

构造方法(默认)

protected ObjectStreamException() {
    super();
}



该类作为对象流异常的顶级类,一般情况下被使用到的是其子类,如下面要提到的OptionalDataException



OptionalDataException继承自ObjectStreamException


该类的类头注释如下:

/**
 * Exception indicating the failure of an object read operation due to
 * unread primitive data, or the end of data belonging to a serialized
 * object in the stream.  This exception may be thrown in two cases:
 *
 * <ul>
 *   <li>An attempt was made to read an object when the next element in the
 *       stream is primitive data.  In this case, the OptionalDataException's
 *       length field is set to the number of bytes of primitive data
 *       immediately readable from the stream, and the eof field is set to
 *       false.
 *
 *   <li>An attempt was made to read past the end of data consumable by a
 *       class-defined readObject or readExternal method.  In this case, the
 *       OptionalDataException's eof field is set to true, and the length field
 *       is set to 0.
 * </ul>
 *
 * @author  unascribed
 * @since   JDK1.1
 */

大意如下:

该类表示读取对象操作失败,原因是无法读取流中对象的基本数据或者是序列化对象的末尾数据,该异常会因两种原因被抛出:

企图读取的对象下一部分是基础数据,在这种情况下,OptionalDataException的长度字段将会被设置为立刻可从流中读出的基础数据字节数,文件结束字段为false

企图使用类声明的readObject或者readExternal方法来读取数据末尾后的部分。在这种情况下,文件结束字段会被设置为true,并且长度字段设置为0



该类含有如下的成员变量:

序列化ID

private static final long serialVersionUID = -8011121865681257820L;

可立刻被读取出的byte长度

public int length;

文件结束标志符

public boolean eof;



该类含有如下的成员方法:

构造函数(第一种情况

OptionalDataException(int len) {
    eof = false;
    length = len;
}

构造函数(第二种情况

OptionalDataException(boolean end) {
    length = 0;
    eof = end;
}



该类的使用方式在注释中已经提到,在这里不再赘述(该类的注释写的有点模糊,说是数据末尾,又说是数据末尾后的非法空间,等到看到了该类的具体抛出位置再来补充和更新)

可以使用双重检查锁定(Double-Checked Locking)结合一些额外的处理来实现满足要求的单例模式。以下是示例代码: ```java import java.io.ObjectStreamException; import java.io.Serializable; class Singleton implements Serializable { private static volatile Singleton instance; private Singleton() { // 防止通过反射重复实例化 if (instance != null) { throw new IllegalStateException("Already initialized."); } } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } // 防止反序列化创建新对象 private Object readResolve() throws ObjectStreamException { return instance; } // 防止克隆 @Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException("Singleton cannot be cloned."); } } ``` 在上述代码中: - 构造方法设为私有,并且在构造方法中检查 `instance` 是否已经被初始化,如果已经初始化则抛出异常,以此禁止重复实例化对象。 - 使用双重检查锁定机制,在 `getInstance` 方法中先检查 `instance` 是否为 `null`,若为 `null` 则进入同步块再次检查,确保在多线程环境下对象初始化的安全性。 - 通过重写 `readResolve` 方法,在反序列化时返回已有的单例实例,确保对象不可通过反序列化破坏单例。 - 重写 `clone` 方法,抛出 `CloneNotSupportedException` 异常,确保对象无法被克隆。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值