Как бороться с различными случаями защитного программирования?
-
21-12-2019 - |
Вопрос
Это пример защитного копирования в Effective java.Предположим, что сценарий в моих базовых вопросах нуждается в защитной копии и не может обойтись без комментария, в котором клиент просит избежать изменения передаваемых объектов.
public Period(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
}
Вопросы:
Что делать, если
Date
у меня не было конструктора, чтобы принять себя, чтобы сделать мое "я" более общим, объект передается без механизма самовоспроизведения, и такой объект нам не принадлежит, т.е. мы не можем изменить его каким-либо образом?Что, если конструктор принял параметр типа в качестве аргумента, скажем
Period(T object)
и T может быть изменяемым, поэтому нуждается в защитной копии.Мы не имеем ни малейшего представления о том, что такое T.Как сделать защитную копию в этом случае?Что такое интерфейс, передается там, где некоторые из его подклассов действительно имеют конструктор типа
Date
чтобы создать объект сам по себе, а некоторые из его подклассов не имеют для этого никакого механизма?Насколько глубоко мы должны копировать в целях защиты?Допустим, мы скопировали массив, но элементы массива были изменяемыми?
Решение
- Если доступно все его состояние, вы можете извлечь его состояние и самостоятельно создать новый объект.В противном случае вы ничего не сможете с этим поделать, кроме как использовать неприятные приемы отражения или сериализации.
- Если T не является экземпляром класса, который позволяет копировать сам себя, вы ничего не сможете сделать.
- Ты ничего не можешь с этим поделать.
- Это зависит.
Прочитав ваш вопрос, я понял, что вы хотели бы повсеместно применять совет "защитного копирования".Ты не должен.В большинстве случаев коду, использующему изменяемые объекты, требуется ссылка на исходный объект, а не на копию.Особенно, если то, что вы получаете в качестве аргумента, является экземпляром абстрактного класса или интерфейса.
Вы вынуждены создать защитную копию Date, потому что это изменяемый тип значения, который не должен быть изменяемым и не был бы им, если бы он был правильно спроектирован.Если вы поддерживаете неизменяемость типов значений, то защитные копии становятся ненужными.Для типов, не содержащих значений, обычно требуется не копия, а ссылка на объект.
Другие советы
- Если вы все равно не можете изменить состояние объекта, вам не нужна защитная копия.
- Единственное, что вы можете сделать, это предположить вероятную реализацию T и проверить их с помощью Экземпляр.
- То же, что и 2.
- На ваше усмотрение.Если вы предполагаете, что модификация элементов массива может нарушить работу вашей программы в других местах, вам также следует скопировать их все.
Защитное программирование имеет значение, когда объекты, которые вы передаете методу, изменяемы.Хорошей практикой (также описанной в книге "Эффективная Java") является то, чтобы сделать их неизменяемыми.
- Если класс Date не является окончательным, вы можете написать для него класс-оболочку, который является подклассом Date.
- Это зависит.Вероятно, в его клонировании не будет необходимости.
- Это не должно тебя беспокоить.Разработчик интерфейса должен позаботиться о проблемах синхронизации.Как правило, хорошей практикой является передача интерфейсов вместо их реализаций.
- Для стандартных коллекций java в java.util есть множество служебных методов.Класс Collections, такой как unmodifiableList и unmodifiableMap, предназначен для использования в защитном программировании.