Java: как обеспечить сериализуемые коллекции

В Java интерфейсы Collection не распространяют Serializable по нескольким веским причинам. Кроме того, большинство распространенных реализаций этих интерфейсов реализуют Serializable.

Таким образом, объекты, реализующие один из интерфейсов Collection, могут быть сериализованы, если сама реализация сериализуема (что обычно бывает) и, если объекты в коллекции все сериализуемы.

Но как я могу обеспечить выполнение этих двух условий? Я не хочу сталкиваться с ошибкой во время выполнения, поскольку компилятор может проверить эти условия. Я думаю о каком-то очевидном интерфейсе, например (showcase для интерфейса List):

public interface SerializableList<T extends Serializable> extends Serializable, List<T> {}

Мне интересно, не сталкивается ли кто-либо с этой проблемой и придумал это простое решение. До сих пор я не мог найти никакого решения или даже дискуссии по этому поводу, что заставляет меня сомневаться в моей идее.

Ответ 1

То, что вы в основном просите, - это определение типа, объединяющее два типа:

<type-def> a = null;

Вам нужно заменить <type-def> спецификацией, убедившись, что объект, на который ссылается a, реализует как Serializable так и Collection<? extends Serializable>. Такое определение типа не поддерживается языком Java.

Как вы уже писали, наиболее очевидным решением может быть объявление вашего собственного интерфейса, присоединение к этим двум другим интерфейсам:

interface SerializableCollection<T extends Serializable> extends Collection<T>, Serializable {}

Кажется, все нормально, пока вы не попробуете что-то вроде этого:

SerializableCollection<String> a = new ArrayList<String>();

Это не будет компилироваться. Даже если ArrayList<String> реализует как Collection<? extends Serializable>, так и Serializable, класс не реализует SerializableCollection<String>.

Теперь вы можете, если хотите, обойти эту проблему, объявив новый класс:

SerializableArrayList<T extends Serializable> extends ArrayList<T> implements SerializableCollection<T> {}

Теперь вы по существу объединили все, что вам нужно, и сможете выполнить первоначальное требование:

SerializableCollection<String> a = new SerializableArrayList<String>();

Это стоит усилий? В вашем случае вы должны решить, но я бы сказал, нет. Мой аргумент заключается в том, что, поскольку маркер Serializable - это просто неформальная метка, гарантирующая, что и ваша коллекция, и ее содержимое реализуют Serializable, все еще не гарантируют сериализацию коллекции и ее содержимого.

Ответ 2

Serializable не является отличным интерфейсом. Это должно было быть аннотацией, если они были доступны, когда они были реализованы.

Как бы вы справились с List List чего-то, кроме Serializable. Вам нужно будет гарантировать, что объект не будет сериализуемым транзитно вниз по графу объектов. Не все объекты, реализующие Serializable, могут быть сериализованы.

Ответ 3

Подход к клонированию коллекции и содержащихся объектов

import org.apache.commons.lang3.SerializationUtils;
...
ClonedArrayList = SerializationUtils.deserialize(SerializationUtils.serialize(OriginalArrayList))

(например, с помощью ArrayList < Тип > (сбор), поскольку SerializationUtils нуждается в интерфейсе Serializable)

С уважением, Гуннар