确定序列化对象的类型。

10
我需要通过套接字发送消息(用户向引擎发送请求和引擎向用户发送响应)。因此,流程基本上是这样的:
       +--------+ serialized  request +--------+      
       | Server | <==== network ====> | Client | 
       +--------+ serialized response +--------+      
           ^                              ^
           | request/response             | mouse/keyclicks
           |    object                    |
           v                              v
       +--------+                     +--------+
       | Engine |                     |  User  |
       +--------+                     +--------+

现在,在这里不重新造轮子是有意义的。我正在处理双方的Java,因此我计划像这样使用对象:

/**
 * A Client makes a Request.
 */
abstract class UserRequest implements Serializable {
    /**
     * The engine will call request.engineCallback(this);
     * This will tell the Engine what the request is, at which point
     * the Engine will determine its response.
     */
    abstract EngineResponse engineCallback(Engine engine);
}

/**
 * The Engine has calculated a Response.
 */
abstract class EngineResponse implements Serializable {
    /**
     * The User will call response.userCallback(this);
     * This tells the User what the Engine thought of its request,
     * and what happened as a result.
     */
     abstract void userCallback(User user);
}

我不理解的是,在我的服务器和客户端套接字中,我怎样才能知道什么子类的 Request 和 Response 正在到达?我看到了这样的情况:

Object request = in.readObject();

// now what? How do I know what to cast it to?

// Can I just cast it like
UserRequest request = (UserRequest)(in.readObject());
engine.addToRequestQueue(request); // let it take care of implementation details?

我的第一个想法是通过字符串传递一切,但是当Java提供序列化时,这似乎有点傻。但是我如何确保知道通过线路传输的是哪个类?说到这个问题,只要我只将UserRequest的后代发送到服务器并将EngineResponse发送到客户端,我需要知道吗?

2个回答

8

只需使用提供的instanceof关键字:

Object o = in.readObject();

if (o instanceof SomeUserRequest)
{
  SomeUserRequest sur = (SomeUserRequest)o;
  ..
}
else if (o instanceof OtherUserRequest)
{
  ..
}

1
@glowcoder:您想要深入了解序列化规范,这位先生。;-) http://download.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.html (是的,类元数据会通过网络传输,以便接收方可以加载类并实例化一个新对象来反序列化状态。) - andersoj
@Jack或者andersoj,我的最后一段代码中,engine.addToRequestQueue(request) - 这是一个被接受的做法吗?我不在乎你给我什么类型的Request,我只是会在我的引擎中使用它的回调方法。 - corsiKa
@glowcoder:是的,看起来不错。当我直接使用序列化时,通常会安排好事情,以便在反序列化之前知道对象的(超级)类型;其他任何事情都太挑剔了。但是,知道超类/接口类型并对其进行分派是完全可以接受的。 - andersoj
1
@glowcoder:没错!为了让你的律师高兴,你应该在代码中加入防御性编程,使用try/catch来捕获ClassCastException异常,以确保程序不会出现问题,从而避免给律师带来大量的计费时间。 - andersoj
@andersoj 最好的部分是... 我问题的真正答案就在我的问题中。当我构思我的问题时,我意识到我不需要知道它是什么类型的请求 - 引擎只会调用回调函数,每个人都会很高兴。我没有意识到 instanceof 会起作用,所以我很高兴我坚持问了我的问题。(当你写了两页纸,你不想只是不发帖子,对吧?) - corsiKa
显示剩余2条评论

0

如果您的协议要与简单序列化一起使用,您需要在连接的两端都有所有要发送的类。

而且您的engineCallback()方法将在服务器上执行,而不是真正的回调到客户端。

如果您想要更多功能(例如在另一侧调用方法,并传递尚未在另一侧可用的类),您可以看看RMI(远程方法调用)。它基于Java序列化协议,但添加了方法调用和能够传递未知类到另一侧以在那里执行的功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接