在Java中访问序列化对象的字段时出现问题
我实例化了一个类,该类在Java中访问序列化对象的字段时出现问题,java,serialization,object,stream,Java,Serialization,Object,Stream,我实例化了一个类,该类实现了可序列化,我正试图像这样流式处理该对象: try{ Socket socket = new Socket("localhost", 8000); ObjectOutputStream toServer = new ObjectOutputStream(socket.getOutputStream()); toServer.writeObject(myObject); } catch (IOException ex) { System.e
实现了可序列化
,我正试图像这样流式处理该对象:
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();
}
}
}
到目前为止一切都很好,对吗?然后我尝试读取该对象的字段,如下所示:
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调用中
这是我第一次流化对象而不是原始数据类型,我做错了什么
奖金
当我正确运行时,整个类是否随序列化对象一起传递(即,我是否有权访问对象类的方法)?我的阅读表明,整个类都与对象一起传递,但到目前为止,我还无法使用objects方法。我如何准确地调用对象的方法
除了上面的代码之外,我还尝试了
readObject
方法,但我可能也用错了,因为我无法让它工作。请告诉我。查看ObjectInputStream.readFields()
的代码,调用该异常是因为curContext
字段为空。在调用readFields()
之前,您应该调用fromClient.readObject()
,因为它将设置curContext
。请注意,readObject()
将返回正在序列化的实例,这可能对您更有用。要回答您的第一个问题:
您需要使用ObjectInputStream.readObject
进行反序列化。无法从流*中读取单个字段
fromClient = new ObjectInputStream(socket.getInputStream());
Object myObject = fromClient.readObject();
写入时不要忘记刷新输出流
第二个问题有点复杂。序列化机制所做的是将类标识符写入流,后跟序列化的对象数据。当它反序列化时,它将读取类标识符并尝试加载该类(如果尚未加载)。然后,它将使用no-arg构造函数实例化对象,并调用privatereadObject(ObjectInputStream)
方法。是的,没错,它从类外部调用私有方法。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
,因为客户端不知道如何查找数据
类
长话短说:类本身并没有写入流。如果反序列化成功,则您将可以访问对象,就像它是本地创建的一样,但您必须将readObject
的结果向下转换为预期类型
版本控制有一些复杂性,我现在已经忽略了。查看serialVersionUID
,以及如果版本控制可能成为一个问题,如何处理对可序列化类的更改
*不完全正确。您可以在可序列化对象的
readObject
方法(或readResolve
)内部调用readFields
,但不能从反序列化机制外部调用它。这有意义吗?这有点难以解释。谢谢,你为我澄清了两个要点。我没有意识到“服务器”和“客户端”都需要相关类的本地副本。我也没有意识到我需要强制转换对象类型。我想现在一切都好了。