将java.lang.Object转换为自定义对象会引发ClassCastException

时间:2011-05-04 17:45:15

标签: java casting

所以,这是一个古怪的问题。我在嵌入式环境中工作,我正在尝试从一个应用程序向另一个应用程序发送消息(对象)。 API标准对象(如java.lang.String)可以正常工作,但是当我尝试发送自定义类的对象时,会引发ClassCastException。

这是设置:我有一个发送者应用程序和一个接收器应用程序。在发送方应用程序中,我实例化一个UserUAI对象(我编写的库中包含的自定义类),将其强制转换为Object,并使用环境API中包含的支持类ComManager将其发送到接收应用程序。但是没关系,它运行正常,就像我之前说的,如果我使用符合API的对象,我没有任何问题。

发送结束:

UserUAI userUAI = new userUAI(/*param list*/);
ComManager.getInstance().sendMessage(targetAppPID, userUAI);
//method signature: void sendMessage(String targetAppPID, Object message)

接收结束:

Object received = (UserUAI)receiver.getReceivedMessage(); 
UserUAI userUAI = (UserUAI)received; //raises exception
//method signature: Object getReceivedMessage();

我检查,双重检查和三重检查,收到的对象在运行时是UserUAI类型。

另外,我发布了PaŭloEbermann给我的建议的结果:

received.getClass() - > class nddigital.support.ricoh.UserUAI

UserUAI.class - > class nddigital.support.ricoh.UserUAI

received.getClass()。getClassLoader() - > jp.co.ricoh.dsdk.osgi.service.multiXletManager.XletClassloader@2d4f9e

UserUAI.class.getClassLoader - > jp.co.ricoh.dsdk.osgi.service.multiXletManager.XletClassloader@4464ab

UserUAC.class == received.getClass() - >假的

UserUAC.class.getClassLoader()== received.getClass()。getClassLoader() - >假

我希望那里的人可以伸出援助之手。我会告诉你的。

6 个答案:

答案 0 :(得分:3)

要讨论§4.3.4的Java Specification部分

  

两种引用类型是相同的运行时类型,如果:

     

它们都是类或两种接口类型,由相同的类加载器定义,   并具有相同的二进制名称(§13.1),在这种情况下,它们有时被称为   相同的运行时类或相同的运行时接口。

     

它们都是数组类型,它们的组件类型是相同的运行时类型(第10节)。

Casting Conversions表示。

  

如果T是类类型,那么R必须是相同的类(§4.3.4)作为T或   T的子类,或抛出运行时异常。

因此,由于不同的类加载器已经定义了相同的类,因此不能将其实例转换为其他类。

答案 1 :(得分:2)

从例外情况来看,receiver.getReceivedMessage()返回的对象显然不是UserUAI类型。如果此方法必须返回Object并且您无法更改它以返回特定类型以防止从对象进行盲目类型转换,那么至少您可以执行

Object received = receiver.getReceivedMessage();
if(received instanceof UserUAI)
{

   UserUAI userUAI = (UserUAI) received;
}

以防止错误。

答案 2 :(得分:2)

从评论到其他答案,看起来你有类加载器问题。

试试这个:

Object received = receiver.getReceivedMessage();

System.out.println(received.getClass());
System.out.println(UserUAI.class);

System.out.println(received.getClass.getClassLoader());
System.out.println(UserUAI.class.getClassLoader());

System.out.println(UserUAI.class == received.class);
System.out.println(UserUAI.class.getClassLoader() == received.getClass.getClassLoader());

即使前两个输出看起来相同,如果由不同的类加载器加载,它们也是不同的类。

要解决此问题,我们需要更多关于您如何使用此内容的背景信息。

答案 3 :(得分:0)

它不起作用,因为receiver.getReceivedMessage()返回的对象不是UserUAI。您可以设置一个断点并确切地找出它返回的内容。

更好的方法是尽可能使用泛型。无法从您展示的代码中真正分辨出来。

答案 4 :(得分:0)

如上所述,返回的对象不是正确的类型。这是一种简单的方法来确定实际返回的对象类型。如果得到NullPointerException,则返回的对象为null

private Object o = receiver.getReceivedMessage();
System.out.println(o.getClass().getName());

答案 5 :(得分:0)

解决方案一直在我面前。我使UserUAI类可序列化并将其作为字节数组发送。在接收端,我反序列化它并将结果对象强制转换为UserUAI,它工作得很好。

Ishtar,感谢你的帖子,这是规范文本给了我这个想法。