gpt4 book ai didi

java - 在 Java 中访问序列化对象的字段时遇到问题

转载 作者:行者123 更新时间:2023-11-30 09:51:19 25 4
gpt4 key购买 nike

我已经实例化了一个 implements Serializable 的类,我正在尝试像这样流式传输该对象:

try{
Socket socket = new Socket("localhost", 8000);
ObjectOutputStream toServer = new ObjectOutputStream(socket.getOutputStream());
toServer.writeObject(myObject);
} catch (IOException ex) {
System.err.println(ex);
}

到目前为止还好吗?然后我尝试像这样读取该对象的字段:

//This is an inner class
class HandleClient implements Runnable{

private ObjectInputStream fromClient;
private Socket socket; // This socket was established earlier

try {
fromClient = new ObjectInputStream(socket.getInputStream());
GetField inputObjectFields = fromClient.readFields();

double myFristVariable = inputObjectFields.get("myFirstVariable", 0);
int mySecondVariable = inputObjectFields.get("mySecondVariable", 0);

//do stuff

} catch (IOException ex) {
System.err.println(ex);
} catch (ClassNotFoundException ex) {
System.err.println(ex);
} finally {
try {
fromClient.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

但我总是得到错误:

java.io.NotActiveException: 未调用 readObject

这是我第一次使用流对象而不是原始数据类型,我做错了什么?

奖金

当我确实让它正常工作时,整个类是否与序列化对象一起传递(即我是否可以访问对象类的方法)?我的阅读表明整个类都是通过对象传递的,但到目前为止我一直无法使用对象方法。我究竟应该如何调用对象的方法?

除了我上面的代码之外,我还尝试了 readObject 方法,但我可能也用错了它,因为我无法让它工作。请赐教。

最佳答案

回答你的第一个问题:

您需要使用ObjectInputStream.readObject 来反序列化。您无法从流中读取单个字段*。

fromClient = new ObjectInputStream(socket.getInputStream());
Object myObject = fromClient.readObject();

不要忘记在写入时刷新输出流!

第二个问题有点复杂。序列化机制所做的是将类标识符写入流,然后是序列化的对象数据。当它反序列化时,它将读取类标识符并尝试加载该类(如果它尚未加载)。然后它将使用无参数构造函数实例化对象并调用私有(private) readObject(ObjectInputStream) 方法。是的,没错,它在类外调用了一个私有(private)方法。 Java 序列化是特殊的。

如果找不到该类(即如果它不在类路径中),则会抛出异常;否则,假设未发现其他错误,您将获得正确类型的完全反序列化对象。

例如,假设您有以下类:

class Server {
public static void main(String[] args) {
// Set up an OutputStream sink, e.g. writing to a socket (not shown)
...
ObjectOutputStream out = new ObjectOutputStream(sink);
out.writeObject(new Data("data goes here"));
out.flush();
out.close();
}
}

class Client {
public static void main(String[] args) {
// Set up an InputStream source (not shown)
...
ObjectInputStream in = new ObjectInputStream(source);
Data d = (Data)in.readObject();
System.out.println(d.getData());
}
}

class Data implements java.io.Serializable {
private String data;
public Data(String d) {
data = d;
}
public String getData() {
return data;
}
}

现在假设您将这些类放入三个 jar 中(每个 jar 一个类):server.jar、client.jar 和 data.jar。如果您运行以下命令,那么它应该一切正常:

java -cp server.jar:data.jar Server
java -cp client.jar:data.jar Client

但是如果你这样做:

java -cp server.jar:data.jar Server
java -cp client.jar Client

然后您将得到一个 ClassNotFoundException,因为客户端不知道如何找到 Data 类。

长话短说:类本身没有写入流。如果反序列化成功,那么您将可以访问该对象,就像它是在本地创建的一样,但您必须将 readObject 的结果向下转换为预期的类型。

我暂时忽略了版本控制的一些复杂性。查看 serialVersionUID 以及在版本控制可能成为问题时如何处理可序列化类的更改。

*不完全正确。您可以在可序列化对象的 readObject 方法(或 readResolve)内部调用 readFields,但不能从反序列化机制外部调用它。那有意义吗?有点难以解释。

关于java - 在 Java 中访问序列化对象的字段时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4703496/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com