Когда это имеет смысл для объекта Java быть сериализуемым, но не Cloneable?

Если класс Java реализует Serializable соедините интерфейсом, но не имейте общественности clone() метод, обычно возможно создать глубокую копию как это:

class CloneHelper {
    @SuppressWarnings("unchecked")
    public static  T clone(T obj) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);
            oos.close();
            byte[] bytes = baos.toByteArray();
            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bais);
            T copy = (T) ois.readObject();
            ois.close();
            return copy;
        } catch (ClassNotFoundException ex) {
            // Shouldn't happen
            throw new Error(ex);
        } catch (IOException ex) {
            // Probably a bug in T's custom serialization methods
            throw new RuntimeException(ex);
        }
    }
}

Я часто встречаюсь со сторонними классами библиотеки как это и обращаюсь к взломам как тот выше. Я даже расширился ObjectOutputStream при случае сделать копию более мелкой. Это никогда не вызывало серьезные проблемы кроме того, чтобы быть неэффективным (медленный для кодирования/декодирования, и временные графики сериализации могут использовать большую память.)

И если не безопасно использовать эту технику, класс, вероятно, не должен был быть объявлен Serializable.

Таким образом, то, что я хотел бы знать, если Ваш класс Serializable, что могло бы препятствовать тому, чтобы Вы определили общественность clone() метод (использующий любого Cloneable взаимодействовать через интерфейс или конструктор копии?)


Похожие страницы: Скопируйте объект в Java

7
задан 3 revs 23 May 2017 в 12:11
поделиться

6 ответов

Вы говорите, что механизм сериализации - это один из способов косвенного "клонирования" объектов. Это, конечно, не является его основной функцией. Обычно он используется для того, чтобы позволить программам передавать объекты по сети, или хранить их в памяти, а затем читать. Можно ожидать, что объект будет использоваться таким образом, и реализовывать Serializable, не ожидая при этом, что код будет клонировать объекты локально, и не реализовывать Cloneable.

Тот факт, что код работает вокруг этого посредством сериализации, говорит о том, что код использует объект так, как не задумывал автор, что может быть либо "виной" автора, либо вызывающего абонента, но это не означает, что в общем случае Serializable и Cloneable идут вместе.

В отдельности я не уверен, что функция clone() "сломана" настолько же хитро, насколько хитро для ее правильной реализации. Конструктор копирования более естественен для использования и получения правильного IMHO.

1
ответ дан 6 December 2019 в 19:36
поделиться

Я бы предпочел использовать конструктор копирования, а не использовать вышеуказанный механизм. Вы можете более тонко определить, что должно быть глубоко или неглубоко скопированным, и сделать копирование объекта, отличного от сериализации объекта. Конструктор копирования может (например) позволяет двум объектам поделиться ссылкой на главный объект, тогда как это может быть не подходит для сериализованного объекта и передается через сеть.

Обратите внимание, что метод к клонному методу широко рассматривается сейчас, как сломан. См. Эта статья с Джошуа Блохом для получения дополнительной информации. В частности, у него нет клона () Метод!

5
ответ дан 6 December 2019 в 19:36
поделиться

Смысл Брайана о Cloneable очень хорош, но даже если Cloneable работал правильно, все равно есть случаи, когда вы можете захотеть, чтобы объект был сериализуемым, но не клонируемым.

Если объект имеет уникальную идентичность, выходящую за рамки процесса, например, представление записи в памяти базы данных, вы не хотите, чтобы она была клонируемой, потому что это эквивалентно созданию новой записи с идентичными атрибутами, включая атрибуты, связанные с идентичностью, такие как ключ базы данных, что почти никогда не является правильным. В то же время, система может быть разбита на несколько процессов по причинам стабильности или по другим причинам, поэтому один процесс может взаимодействовать с базой данных и генерировать эти объекты "ENTITY" (см. "Domain-Driven Design" Эрика Эванса (Eric Evans) для получения дополнительной информации о поддержании согласованности идентификаторов объектов в приложении, поддерживающем данные), но отдельный процесс может использовать эти объекты для выполнения операций бизнес-логики. Объект сущности должен быть сериализуем, чтобы его можно было передавать от одного процесса к другому.

4
ответ дан 6 December 2019 в 19:36
поделиться

Одной из самых больших проблем с сериализацией является то, что их нельзя легко сделать неизменными. Сериализация заставляет вас сделать компромисс здесь.

Я был бы соблазнен создавать копии конструкторов вниз по графику объекта. Это чуть более груз, чтобы сделать.

1
ответ дан 6 December 2019 в 19:36
поделиться

Если вы хотите добавить собственную библиотеку, не вмешиваясь в java.library.path во время разработки в Eclipse (чтобы не включить абсолютные пути и необходимость добавления параметров на конфигурацию запуска), вы можете поставить Путь к местным библиотекам Расположение для каждой банки в диалоговом окне Path диалог под Нативное местоположение библиотеки . Обратите внимание, что нативное имя файла библиотеки должно соответствовать имени файла JAR. Смотрите также это Подробное описание .

-121--782992-

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

-121--3909817- [11749817-

, который поражает меня как вроде опасного, поскольку существует ряд ловушек для сериализации, (хотя большинство из них вряд ли я все равно хотел бы проверить их, если бы я сериализую объекты в 3D партийных библиотеках). Вряд ли будет распространенным вопросом, но можно иметь объект с волатильной переменной в рамках его состояния, который может быть частью операции клонирования (не то, что это хороший дизайн, только что это возможно), и такой Поле не будет скопировано в процессе сериализации / десериализации. Еще одна проблема, которая приходит к уму, заключается в том, что константы и возможность получения нескольких копий таких вещей, если вы не имеете дело с ними во время десериализации.

Опять, краевые чехлы, но то, что вы хотели бы осмотреть.

0
ответ дан 6 December 2019 в 19:36
поделиться

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

2
ответ дан 6 December 2019 в 19:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: