Java 从ObjectInputStream读取对象(自定义)

Java 从ObjectInputStream读取对象(自定义),java,client-server,objectinputstream,objectoutputstream,Java,Client Server,Objectinputstream,Objectoutputstream,所以,我不知道为什么我的项目的客户部分会给我这种类型的错误 线程“main”java.lang.ClassNotFoundException:Mining.FrequentPatternMiner中的异常 位于java.net.URLClassLoader$1.run(未知源) 位于java.net.URLClassLoader$1.run(未知源) 位于java.security.AccessController.doPrivileged(本机方法) 位于java.net.URLClassLo

所以,我不知道为什么我的项目的客户部分会给我这种类型的错误

线程“main”java.lang.ClassNotFoundException:Mining.FrequentPatternMiner中的异常 位于java.net.URLClassLoader$1.run(未知源) 位于java.net.URLClassLoader$1.run(未知源) 位于java.security.AccessController.doPrivileged(本机方法) 位于java.net.URLClassLoader.findClass(未知源) 位于java.lang.ClassLoader.loadClass(未知源) 位于sun.misc.Launcher$AppClassLoader.loadClass(未知源) 位于java.lang.ClassLoader.loadClass(未知源) 位于java.lang.Class.forName0(本机方法) 位于java.lang.Class.forName(未知源) 位于java.io.ObjectInputStream.resolveClass(未知源) 位于java.io.ObjectInputStream.readNonProxyDesc(未知源) 位于java.io.ObjectInputStream.readClassDesc(未知源) 位于java.io.ObjectInputStream.ReadOrderinaryObject(未知源) 位于java.io.ObjectInputStream.readObject0(未知源) 位于java.io.ObjectInputStream.readObject(未知源) 位于JabberClient.main(JabberClient.java:81)

在服务器部分,我强制转换FrequentPatternMiner变量,然后将其提供给ObjectOutputStream

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

FrequentPatternMiner fpMiner=new FrequentPatternMiner(dataTarget, minsup);  
fpMiner.salva("FP_"+nameFile+"_minSup"+minsup+".dat");
System.out.println("Frequent Patterns \n"+fpMiner);

out.flush();
out.writeObject((Object)fpMiner);
在客户端,我这样做

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

Object fpMiner=in.readObject();
(((ObjectInput)in).readObject());
System.out.println(fpMiner);
如何修复代码?你能帮我吗?

你得走了

System.out.println((FrequentPatternMiner )fpMiner);
否则,客户端将如何知道正在反序列化的对象的类。注意:仅在
sysout
中使用它,不必进行类型转换。它将使用Objects
toString()
方法打印

尽管你的特例说

Exception in thread "main" java.lang.ClassNotFoundException

您还需要在客户端添加这个类。最后检查服务器和客户端中的类的
serialVersionUID
是否相同

您遇到的问题是
FrequentPatternMiner
不在您的类路径上

您可以在Eclipse上执行
ctrl+t
,并查找FrequentPatternMiner以了解包含此类的jar是什么。然后确保您的项目正在引用此类


如果您使用的是maven,那么您可以使用
mvm dependency:tree
goal来了解您的项目是否包含此jar。

代码是正确的,但前提不是正确的。您已经说过,类“
FrequentPatternMiner
对于客户端来说必须是未知的”。在这个前提下,您不能像以前那样序列化类,因为序列化只传输对象的数据,而不传输对象的实现。 您可能希望查看DataTransferObjects(必须在客户端和服务器上都知道),或者使用一个简单的数组来传输对象

使用简单数组作为“DTO”的示例

服务器:

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

// The following line assumes that dataTarget and minsup are types 
// that are serializable and known to the client
Object[] objArray = new Object[] { dataTarget, minsup };

out.flush();
out.writeObject(objArray);
客户:

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

Object[] objArray = (Object[])in.readObject();
System.out.println(objArray);

// FrequentPatternMiner must still known to the client, if you need more than 
// the constructor arguments (like methods of the FrequentPatternMiner) Object.
FrequentPatternMiner fpMiner=new FrequentPatternMiner(objArray[0], objArray[1]);
进一步的想法 如果不希望客户机知道FrequentPatternMiner实现/类,可以尝试“远程处理”或“远程过程调用”(RPC)。这是一门高级学科,有很多图书馆(和平台)提供这一功能。他们基本上是这样做的:

  • 客户机上的类需要一个接口(如
    接口IPatternMiner{void doMine()}
  • 连接服务器和客户端(取决于库的操作方式)并获取
    IPatternMiner的实例
  • 在接口上调用一个方法,实现在服务器上执行(参数从客户端传入)

向对象强制转换没有任何魔法属性。任何东西都可以向对象强制转换。这不会改变写入对象流的内容是FrequentPatternMiner的事实,如果该类在接收方不可用,则会导致此异常

解决方案:部署类


类似地,将ObjectInputStream强制转换为ObjectInput也不会产生任何效果。

谢谢您的回答;)。对于客户端,FrequentPatternMiner类必须是未知的。我做了两个不同的项目,服务器和客户端。在服务器中,我放置了包含所有类的不同包,在客户端,我只放置了与服务器部分连接的部分
System.out.println((FrequentPatternMiner)fpMiner)类型转换是完全不必要的。是的,但由于将调用对象
toString()
,因此没有多大意义。OP不需要类型转换。该对象已属于该类。你关于Object.toString()的评论是毫无意义的。这不是100%正确的。如果FrequentPatternMiner实现了toString,那么不管强制转换是什么,都会调用它的toString实现。所以
class Untitled{public static class Blob{public String toString(){return“mine”;}}}public static void main(String[]args){Blob b=new Blob();System.out.println(b);Object c=b;System.out.println(c);}}
返回相同的值。感谢您的回答,FrequentPatternMiner jar位于服务器项目中,客户端不应具有此属性class@user3786467给出错误的应用程序的类路径上肯定没有jar。谢谢你的回答,你能给我举个例子吗?我必须实现DataTransferObject,或者我只能在两个项目中导入?如何使用简单数组?是否有应在客户端上执行的
FrequentPatternMiner
方法?然后,如果不让客户机知道jar中的类,就没有办法(读简单的方式)。您正在尝试反序列化它没有的类。我建议您创建一个包含服务器和客户端之间共享的所有对象的jar,并确保两端的jar版本相同。如何创建此jar?我将使用
maven
,但您可以使用
ant
jar
命令,或者IDE中的一个插件。@这个对象是否具有神奇的属性?不部署类?认真地你的观点是什么?