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

发布于 2024-11-05 06:06:25 字数 1467 浏览 0 评论 0原文

所以,这是一个奇怪的问题。我在嵌入式环境中工作,尝试将消息(对象)从一个应用程序发送到另一个应用程序。 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ŭlo Ebermann 给我的建议的结果:

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

UserUAI.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 == receive.getClass() -> false

UserUAC.class.getClassLoader() == receive.getClass().getClassLoader() -> false

我希望有人能帮我一把。我会随时通知您。

So, this is an oddball issue. I work in an embedded environment and I'm trying to send a message (object) from one application to another application. API-standard objects such as java.lang.String will work just fine, but when I try to send an object fo a custom class, a ClassCastException is raised.

Here's the setup: I have a sender application and a receiver application. In the sender application, I instantiate an UserUAI object (a custom class included in a library I wrote), cast it to Object and send it to the receiving application using the supporting class ComManager included in the environment API. But that's ok, it works fine, and like I said before, if I use API-compliant objects, I have no problem whatsoever.

Sending end:

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

Receiving end:

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

I checked, double checked and triple checked, the received object is of UserUAI type at runtime.

Also, I'm posting the results of a suggestion that Paŭlo Ebermann gave me:

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() -> false

UserUAC.class.getClassLoader() == received.getClass().getClassLoader() -> false

I hope someone out there can lend me a hand. I'll keep you posted.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一笔一画续写前缘 2024-11-12 06:06:25

引用 Java 规范 部分§4.3.4

如果满足以下条件,则两个引用类型是相同的运行时类型:

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

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

铸造转换中它说。

如果 T 是类类型,则 R 必须与 T 相同的类 (§4.3.4)
T 的子类,或者抛出运行时异常。

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

To qoute the Java Specification part of §4.3.4

Two reference types are the same run-time type if:

They are both class or both interface types, are defined by the same class loader,
and have the same binary name (§13.1), in which case they are sometimes said to be the
same run-time class or the same run-time interface.

They are both array types, and their component types are the same run-time type(§10).

And in Casting Conversions it says.

If T is a class type, then R must be either the same class (§4.3.4) as T or
a subclass of T, or a run-time exception is thrown.

So, since the same classes have been defined by different class loaders, its instances can not be cast to other.

儭儭莪哋寶赑 2024-11-12 06:06:25

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

试试这个:

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());

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

为了解决这个问题,我们需要更多关于您如何使用它的背景信息。

From the comments to the other answers, it looks like you have classloader issues.

Try this:

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());

Even if the first two outputs look same, they are different classes if loaded by different classloaders.

To solve this, we will need more context about how you are using this.

月竹挽风 2024-11-12 06:06:25

从异常中可以明显看出,receiver.getReceivedMessage() 返回的对象不是 UserUAI 类型。如果此方法必须返回 Object 并且您无法更改它以返回特定类型以防止从对象进行盲目类型转换,那么至少您可以采取措施

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

   UserUAI userUAI = (UserUAI) received;
}

来防止错误。

From the exception, clearly the object returned by receiver.getReceivedMessage() is not of type UserUAI. If this method has to return Object and you cannot change it to return a specific type so you prevent a blind type cast from object, then atleast you could do

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

   UserUAI userUAI = (UserUAI) received;
}

to prevent the error.

甜柠檬 2024-11-12 06:06:25

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

更好的方法是如果可能的话使用泛型。从您所显示的代码中无法真正看出。

It doesn't work because the object returned by receiver.getReceivedMessage() isn't a UserUAI. You could set a breakpoint and find out exactly what it is returning.

A better approach would be to use generics if at all possible. Can't really tell from the bit of code you've shown.

骄兵必败 2024-11-12 06:06:25

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

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

As said above, the object being returned is not of the right type. Here's an easy way to figure out what type of object is actually being returned. If you get a NullPointerException, then the object returned was null

private Object o = receiver.getReceivedMessage();
System.out.println(o.getClass().getName());
沦落红尘 2024-11-12 06:06:25

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

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

The solution was in front of me the whole time. I made the UserUAI class serializable and sent it as a byte array. In the receiving end, I deserialize it and cast the resulting object to UserUAI and it works just fine.

Ishtar, thanks for your post, it was the specification text that gave me the idea.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文