ObjectInputStream()' 在 'java.io.ObjectInputStream' 中具有 protected 访问权限
时间: 2023-06-13 09:06:42 浏览: 93
这个错误通常发生在尝试从文件或网络流中反序列化对象时。这是因为ObjectInputStream的构造函数是受保护的,只能从子类中访问。
解决方法是创建一个子类继承ObjectInputStream,然后在子类中实现一个公共构造函数来调用父类的受保护构造函数。例如:
```java
public class MyObjectInputStream extends ObjectInputStream {
public MyObjectInputStream(InputStream in) throws IOException {
super(in);
}
}
```
然后你可以使用MyObjectInputStream来反序列化对象。
相关问题
Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable. To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime. During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream. When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object. Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures: private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException;
一个类实现了java.io.Serializable接口就可以启用类的序列化功能。没有实现这个接口的类将不会序列化或反序列化其任何状态。可序列化类的所有子类型也都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
为了允许非可序列化类的子类型被序列化,子类型可以承担起保存和恢复超类型的公共、受保护和(如果可访问)包字段状态的责任。只有当扩展的类具有可访问的无参构造函数来初始化类的状态时,子类型才能承担这个责任。如果不满足这个条件,声明一个类为Serializable将会导致错误,在运行时将会被检测到。
在反序列化过程中,非可序列化类的字段将使用该类的公共或受保护的无参构造函数进行初始化。无参构造函数必须对可序列化的子类可访问。可序列化子类的字段将从流中恢复。
在遍历图形时,可能会遇到不支持Serializable接口的对象。在这种情况下,将抛出NotSerializableException,并且会标识非可序列化对象的类。
需要在序列化和反序列化过程中进行特殊处理的类必须实现具有以下确切签名的特殊方法:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
如何在Java中实现对象的深拷贝?
在Java中实现对象的深拷贝通常有以下几种方法:
1. 实现Cloneable接口并重写Object类中的clone()方法:这种方式需要在类中实现Cloneable接口,并且重写clone方法,在其中进行深拷贝的实现。需要注意的是,为了确保深拷贝,所有引用类型的成员变量也需要提供相应的clone方法,以保证成员变量也被深拷贝。
```java
public class MyObject implements Cloneable {
private int[] data;
public MyObject() {
data = new int[10];
}
@Override
protected Object clone() throws CloneNotSupportedException {
MyObject clone = (MyObject) super.clone();
clone.data = data.clone(); // 确保数据数组也被深拷贝
return clone;
}
}
```
2. 通过对象序列化:使用序列化和反序列化也可以实现深拷贝。首先将对象写入流中(序列化),然后再从流中读回来(反序列化),这样得到的将是完全独立的对象副本。
```java
import java.io.*;
public class DeepCopy {
public static MyObject deepCopy(MyObject obj) {
try {
// 将对象写入流中
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
// 从流中读回对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (MyObject) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
```
3. 通过复制构造器:创建一个新的类实例,并手动将原对象的所有成员变量复制到新对象中。这个方法要求手动实现所有成员变量的复制逻辑,但更灵活可控。
```java
public class MyObject {
private int[] data;
public MyObject(MyObject original) {
this.data = original.data.clone(); // 确保数据数组也被深拷贝
}
}
```
需要注意的是,无论采取哪种方式,都必须确保对象中的所有成员变量都是可复制的,且不会因为复制操作而产生问题。