将 Serializables 数组从一个活动传递到另一个活动时发生 Class Cast Exception

Posted

技术标签:

【中文标题】将 Serializables 数组从一个活动传递到另一个活动时发生 Class Cast Exception【英文标题】:Class Cast Exception when passing array of Serializables from one activity to another 【发布时间】:2015-04-27 12:12:04 【问题描述】:

我有一个包含可序列化对象的数组,我正在尝试使用 Intent 的 putExtra() 和 Bundle 的 getSerializable()。但是,我得到一个类转换异常并且不明白为什么。

下面是代码。 UserInfo 是我自己的实现 Serializable 的类,并且我已经能够在活动之间传递单个 UserInfo 对象。我只是在尝试使用数组时遇到了这个问题。

发送可序列化的代码:

Intent intent = new Intent( JOIN_GROUP ); //JOIN_GROUP is a constant string

String user_ids[] = packet.userIDs();

int length = user_ids.length;
UserInfo users[] = new UserInfo[length];

for ( int i = 0; i < length; ++i )
    users[i] = getUserByID( user_ids[i] );

intent.putExtra( USERS_IN_GROUP, users );

检索可序列化的代码:

Bundle extra = intent.getExtras();          
String action = intent.getAction();

if ( action.equals(IMService.JOIN_GROUP) )
   
    //CLASS CAST EXCEPTION
    UserInfo users[] = (UserInfo[]) extra.getSerializable( IMService.USERS_IN_GROUP ); 

这是错误:

问题

我知道我可能只使用不同的数据结构,但我想了解为什么数组不能工作,因为数组是可序列化的?

编辑: SnyersK 能够让一个更简单但类似的方案发挥作用。 所以我尝试了同样的事情,但我仍然得到同样的例外。它在检索数组时将我的测试数组变成了一个对象,这导致了强制转换异常。

我的测试对象:

package types;

import java.io.Serializable;

public class Test implements Serializable 

    private static final long serialVersionUID = 1L;

    private String hello = "hello";


传递测试对象数组的代码:

Test myArray[] = new Test[]  new Test(), new Test() ;
Intent i = new Intent( this, Login.class );
i.putExtra( "key", myArray );

检索测试对象数组的代码:

Bundle extras = getIntent().getExtras();
Test array[] = (Test[]) extras.getSerializable( "key" ); //Class Cast Exception

【问题讨论】:

用一些错误日志更新问题。 看到这个了吗? ***.com/a/14333555/233048 我只是尝试自己传递一个可序列化对象的数组,但没有看到任何错误。您 100% 肯定您在启动第二个活动之前不会使用相同的字符串添加另一个额外内容? @SnyersK 这很奇怪。我是 100% 积极的。我在一个班级中只有一个地方可以做到这一点。并将数据结构更改为 ArrayList 有效。我还在代码中添加了许多日志语句,以确保这两个 sn-ps 正在执行。您是说您没有在您自己的自定义可序列化对象数组上获得类转换异常?无论出于何种原因,运行时对象都会变成 Object 类的实例,而不是保留为 UserInfo 数组。 是的,我使用自定义对象Test 编写了一个快速测试,该对象仅包含一个字符串并实现了可序列化。我制作了一个包含 5 个对象的数组,并在开始第二个活动时将其作为额外的。这一切都很好。我没有错误,我的对象都在我的第二个活动中。 【参考方案1】:

替换

intent.putExtra( USERS_IN_GROUP, users );

intent.putExtra( USERS_IN_GROUP, new ArrayList<UserInfo>(Arrays.asList(users)));

【讨论】:

我得到一个编译器错误使用这个:The method putExtra(String, boolean) in the type Intent is not applicable for the arguments (String, List&lt;UserInfo&gt;)。考虑到 asList() 的描述说它返回一个可序列化的列表,我认为这也可以。 试试 bundle.putparcelable() @Zygotelnit 我相信你,但问题是添加额外内容时编译器错误。目前,我将返回的对象从 getSerializable() 转换为什么并不重要,因为直到运行时才会发生。 UserInfo需要实现Serializable我猜 确实如此。在过去的几周里,我已经能够在它上面使用 getSerializable()。【参考方案2】:

试试这样:

Intent intent = new Intent( JOIN_GROUP ); //JOIN_GROUP is a constant string

String user_ids[] = packet.userIDs();

int length = user_ids.length;
UserInfo users[] = new UserInfo[length];

for ( int i = 0; i < length; ++i )
    users[i] = getUserByID( user_ids[i] );

Bundle bnd=new Bundle();
bnd.putSerializable(USERS_IN_GROUP, users);

在发送时附加到意图,而在返回时,您正在从包中读取(这是意图附加)。

【讨论】:

我不认为这是问题所在。在过去的几周里,我已经能够使用我的方法成功地传递可序列化对象。我只在使用数组时遇到了问题。所以我不确定为什么这会解决它。【参考方案3】:

显然,这是旧版本 android 上的错误。 (5.0.1 版是唯一一个可以正常工作的测试版本,也许它可以从 5.0 及更高版本开始运行)

错误

假设我们有一个名为User 的对象数组,它实现了Serializable

User[] users;

当我们尝试通过这样的意图将该数组传递给另一个活动时

intent.putExtra("myKey", users);

我们的users 将转换为Object[]

如果我们尝试从第二个活动的意图中获取我们的数组,像这样

User[] users = getIntent().getSerializableExtra("myKey");

我们会得到一个 ClassCastException。

从文档中,我们可以得出结论,这应该不是问题,因为Array 是一个可序列化的类,并且自api 1 以来已添加putExtra(String key, Serializable value)

如果您想在 Android 5.0.1 之前的 Android 版本上通过 Intent 传递Array(也许一些旧版本也可以,但直到 Android 4.3 才可以正常工作) 你必须解决它。您可以通过将 Array 转换为 ArrayList 来做到这一点。

编辑

另一种解决方法是将您的额外内容复制到一个新数组中,因此不必强制转换它。不过,我不确定该方法的积极/消极后果。它看起来像这样:

Object[] array = (Object[]) getIntent().getSerializableExtra("key");
User[] parsedArray = Arrays.copyOf(array, array.length, User[].class);

我在这里找到了这个方法:How to convert object array to string array in Java。

【讨论】:

你应该提到 User 实现了 Serializable。 抱歉,不是要挑剔,它会转换为Object,而不是Object[]。如果有人担心使用ArrayList 会浪费空间,他们总是可以将他们想要的初始容量传递给构造函数,从而获得与使用基本数组几乎相同的空间量。 (我说“几乎”是因为 ArrayList 有更多实例变量,但没什么大不了的。)很好的答案。 我的堆栈跟踪说它是Object[]Caused by: java.lang.ClassCastException: java.lang.Object[] cannot be cast to my.package.testing.Test[] 哦,好吧,我想我只是没有解释在 logcat 中产生的堆栈跟踪(以及 tbh idk 如何)。再次感谢。 我看到其他人也将其写为[Ljava.lang.Object;。我想' [L ' 意味着它是一个数组。顺便说一句,我添加了另一种可能的解决方法。【参考方案4】:

UserInfo 是内部类还是单独的 java 类文件?

如果是内部类,那么父类也应该是Serializable。

如果没有,让UserInfo 类实现Parcelable 并使用

intent.putParcelableArrayListExtra(USERS_IN_GROUP, new ArrayList<UserInfo>(Arrays.asList(users)));

【讨论】:

这是一个单独的类。 实现 Parcelable 比实现 Serializable 需要付出更多的努力,而且目前效率不是问题,所以我想使用 Serializable。此外,我将不得不更改许多代码行,因为将 UserInfo 作为 Serializable 对象传递的方法与 Parcelable 不同。我正在制作一个聊天应用程序,因此 UserInfo 对象被传递了很多。

以上是关于将 Serializables 数组从一个活动传递到另一个活动时发生 Class Cast Exception的主要内容,如果未能解决你的问题,请参考以下文章

无法通过intent将数组列表从一个活动传递到另一个活动

将Serializable数组从一个活动传递到另一个活动时的类Cast Exception

将对象的嵌套数组列表从适配器传递到活动

如何将字节数组一个活动传递给另一个android [重复]

如何将数组传递给另一个活动?

使用自定义视图将字符串数组传递给另一个活动