Java ClassCastException,在不同的包中有两个相同的类,通过网络发送

时间:2014-12-08 21:33:22

标签: java sockets package classcastexception

我遇到以下问题:我的项目由两个包(客户端和服务器)组成,其中每个包都有类Package。现在,我想通过ObjectOutputStream / ObjectInputStream通过网络发送此课程,如下所示:

//Client - this is in package client
ObjectOutputStream out = new SocketOutputStream(socket.getOutputStream);
Package package = new Package();
out.writeObject(package);

//Server - this is in package server
ObjectInputStream in = new SocketInputStream(socket.getInputStream);
Object o = in.readObject();
if(o instanceof Package) ... //do something important

所以问题出在最后一行,我得到一个ClassCastException。原因显然是他采用完整路径来确定对象的类型,因此client.Package不是server.Package。问题是我不能将客户端包放到服务器上,反之亦然。

所以这是真正的问题:我可以在不从包(客户端/服务器)导入Package类的情况下确定类的类型吗?或者是否有可能通过网络发送对象而没有类信息?


编辑: Package类如下所示:

public class Package implements Seriablizable {
    private static final long serialVersionUID = 5050301321863757269L;

    public String objectName;
    public Object[] parameters;
    public Class[] parameterTypes; //parameter types
}


已经感谢您的帮助:)。

4 个答案:

答案 0 :(得分:2)

  

原因显然是他采用完整路径来确定对象的类型,因此client.Package不是server.Package。问题是我不能将客户端包放到服务器上,反之亦然。

您只需完成此操作,或将其放入客户端和服务器均可访问的第三个包中。

或者在类中实现writeReplace()readResolve(),但这意味着执行该操作的类必须知道另一个包中的另一个类,这可能会破坏您的包问题另一种方式。

答案 1 :(得分:2)

当您在不同的包中声明两个具有相同名称的类时,它们是根本不同的类。这就是当您尝试从一种类型转换为另一种类型时获得异常的原因。

  

问题是我无法将客户端软件包放到服务器上,反之亦然。

你无法说服Java类型系统这两个类是相同的。他们是不同的。

最简单的解决方案是创建第三个包,其中包含客户端和服务器端所需的类。将公共包(或包)放入JAR文件中,并将其添加到客户端和服务器端的类路径中。

还有其他替代方案,例如:

  • 使用不同的编组/解组机制(JSON,XML,自定义)或

  • 使用Java序列化库中的可用钩子来翻译类型(参见@ EJP'答案),

但是(请记住)这个问题归结为一个设计错误,最好的方法是尽快修复错误 而不是用它来解决。

如果您通过Java序列化将对象从java客户端传递到Java服务器,那么您应该在两端使用相同的类。如果由于合理的技术原因(不同于设计错误)不可能,那么这很可能是不使用Java序列化的好理由。


回答你真实的"问题:

  

问:我可以在不从包(客户端/服务器)导入Package类的情况下确定类的类型吗?

严格的是,但它不会帮助你。

  • 您可以通过其完全限定名称来引用类; e.g。

    if (o instanceof com.acme.WeaselTrap)
    
  • 您可以获取实际类型的Class对象。

    Class<?> clazz = o.getClass();
    

但是一旦你到了那里,你仍然会遇到这样的问题,即不同包中具有相同名称的两种类型根本不同

(当然,如果您的代码可以应对不同的类,您可以通过更改类名来简化您的生活,以便简单名称不同。)

  

问:或者是否有可能通过网络发送没有类信息的对象?

不使用Java序列化。

答案 2 :(得分:0)

你的instanceof不应该是Package不是包吗?因为它是一个班级名称。

您可以将对象作为xml或json来回发送。数据可以编组和解组到任何你想要的类。

例如: Marshall/Unmarshall a JSON to a Java class using JAXB

答案 3 :(得分:0)

它不起作用的原因是因为你可能没有在你的班级中实现Java的序列化机制。如here所述,您所要做的就是让您的类实现java.io.Serializable。即使绝对路径不同,如果client.Package和server.Package中的代码相同,这将正常工作。请注意,如果Package类中的任何结构不是本机Java类型,那么这些结构也必须实现java.io.Serializable。