我遇到以下问题:我的项目由两个包(客户端和服务器)组成,其中每个包都有类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
}
已经感谢您的帮助:)。
答案 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来回发送。数据可以编组和解组到任何你想要的类。
答案 3 :(得分:0)
它不起作用的原因是因为你可能没有在你的班级中实现Java的序列化机制。如here所述,您所要做的就是让您的类实现java.io.Serializable。即使绝对路径不同,如果client.Package和server.Package中的代码相同,这将正常工作。请注意,如果Package类中的任何结构不是本机Java类型,那么这些结构也必须实现java.io.Serializable。