Список Java, который клонирует элементы при добавлении - PullRequest
2 голосов
/ 03 июня 2019

Существует ли класс Java, который реализует интерфейс List и какие элементы клонируются при добавлении в список?Цель этого состоит в том, чтобы сохранить инкапсуляцию этого списка в виде объекта.

Конечно, было бы легко написать один сам, взяв, скажем, ArrayList и обернув его в другом классе, затем вызвав клонметод при реализации методов добавления и получения.Но я решил спросить, был ли такой класс уже предоставлен Java, и потенциально избавил бы меня от утомительного кодирования.

Ответы [ 2 ]

4 голосов
/ 03 июня 2019

Я сомневаюсь, что одна существует, по нескольким причинам:

  1. Как этот список должен клонировать элементы?Object.clone() работает только для типов, которые реализуют @Cloneable;и когда он работает, он делает только поверхностную копию (например, если объект имеет поле List, он клонирует ссылку на объект списка, но не его элементы);победить свою собственную цель. Информация о проблемах клонирования Java .Таким образом, чтобы клонирование действительно работало, клонируемый тип должен переопределить Object.clone() при правильной реализации.Это означает, что ваш «список клонирования» должен знать, правильно ли реализован содержащийся тип clone(), и даже если ему удастся это сделать, он будет полезен только с очень ограниченным набором типов.
  2. Для типов, которые действительно реализуют clone(), довольно просто сделать list.add(elem.clone()) вместо list.add(elem).Совершенно новый тип списка с оговорками, упомянутыми в пункте 1, просто чтобы избавить нас от ввода 8 символов, не кажется очень полезной вещью.
2 голосов
/ 03 июня 2019

Не существует стандартного способа иметь реализацию любой Коллекции, которая автоматически клонирует свои объекты по мере их добавления.

Если вы действительно хотите, вы можете создать свою собственную реализацию List и использовать отражение , чтобы клонировать каждый входящий и выходящий объект. Когда задают такой вопрос, я никогда не рекомендую вам создавать свою собственную реализацию чего-либо в библиотеке Коллекций. Я думаю, что единственная причина для создания собственной реализации в этом случае заключается в том, что если у вас есть какая-то другая библиотека, которая принимает список или коллекцию в качестве параметра, и вы действительно не хотите, чтобы значения этой коллекции были видоизменены.

Существует также возможность не сохранять изменяемые данные в списке. Вы всегда можете создать неизменные реализации данных, которые вы хотите сохранить в коллекции. Если возможно, это вариант, с которым я бы пошел. Если вы пойдете по этому пути, вам все равно придется убедиться, что элементы Data являются неизменяемыми или вместо них есть List<ImmutableData>. Использование List<ImmutableData> может быть неплохой идеей, но вам, вероятно, придется иметь List<? extends Data> в большинстве сигнатур методов.

Это может выглядеть так:

interface Data {
    String getString();
    MutableData toMutable();
}
class MutableData implements Data {
    String getString() {...}
    void setString(String s) {...}
    Data toImmutable() {...}
    MutableData clone() {...}
}
class ImmutableData implements Data {...}

Если вы по-прежнему хотите клонировать, но не хотите использовать рефлексию или решать все проблемы, связанные с интерфейсом Cloneable, вы можете создать собственный более общий интерфейс для целей вашего приложения.

...