У меня есть массив, содержащий сериализуемые объекты, и я пытаюсь использовать putExtra () от Intent и getSerializable () из Bundle. Однако я получаю исключение приведения класса и не понимаю, почему.
Ниже приведен код. 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
4 ответа
Видимо это ошибка в старых версиях Android. (Версия 5.0.1 - единственная протестированная версия, на которой она работает, как ожидалось, возможно, она работает с 5.0 и выше)
Ошибка
Допустим, у нас есть массив объекта с именем User
, который реализует Serializable
.
User[] users;
Когда мы пытаемся передать этот массив другому действию с помощью такого намерения
intent.putExtra("myKey", users);
Наш users
будет преобразован в Object[]
.
Если мы попытаемся получить наш массив из намерения во втором действии, например, так
User[] users = getIntent().getSerializableExtra("myKey");
Мы получим исключение ClassCastException.
Из документации мы можем сделать вывод, что это не должно быть проблемой, поскольку Array
является сериализуемым классом, а putExtra(String key, Serializable value)
был добавлен после api 1
.
Если вы хотите передать Array
через намерение в версиях Android до Android 5.0.1 (возможно, некоторые старые версии также работают, но до Android 4.3 это НЕ работает) Вам придется обойти это. Вы можете сделать это, преобразовав свой Array
в ArrayList
.
ИЗМЕНИТЬ
Другой обходной путь - это копирование вашего дополнения в новый массив, поэтому вам не нужно его приводить. Однако я не уверен в положительных / отрицательных последствиях этого метода. Это выглядело бы так:
Object[] array = (Object[]) getIntent().getSerializableExtra("key");
User[] parsedArray = Arrays.copyOf(array, array.length, User[].class);
Я нашел этот метод здесь: Как преобразовать массив объектов в строковый массив в Java.
Это внутренний класс UserInfo
или отдельный файл класса Java?
Если это внутренний класс, то родительский класс также должен быть сериализуемым.
Если нет, сделайте UserInfo
класс реализацией Parcelable
и используйте
intent.putParcelableArrayListExtra(USERS_IN_GROUP, new ArrayList<UserInfo>(Arrays.asList(users)));
Попробуйте вот так:
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);
При отправке вы присоединяетесь к намерению, а во время ретрвнга вы читаете из пакета (что является дополнительным намерением).
Заменить
intent.putExtra( USERS_IN_GROUP, users );
С участием
intent.putExtra( USERS_IN_GROUP, new ArrayList<UserInfo>(Arrays.asList(users)));
Похожие вопросы
Связанные вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.