Защитное копирование в терминах ссылочного параметра в конструктор
Может кто-нибудь, пожалуйста, скажите мне, что такое защитное копирование с точки зрения ссылочного параметра в конструктор класса в JAVA
Спасибо оооочень большое
1 ответ
Учитывая, что я могу извлечь из вопроса, я думаю, что проблема может быть резюмирована следующим образом...
Давайте начнем с этого:
class NotSafeAtAll
{
private final List<X> list;
public NotSafeAtAll(final List<X> list)
{
this.list = list;
}
}
Этот класс имеет огромную проблему: он копирует ссылку на список в качестве своего поля члена. Это означает, что если вызывающий конструктор изменяет этот список, изменения будут отражены в NotSafeAtAll
экземпляр также.
И вот тут "оборонительное копирование" вступает в игру. Рассматривать:
class ALittleMoreSafe
{
private final List<X> list;
public ALittleMoreSafe(final List<X> list)
{
this.list = new ArrayList<X>(list);
}
}
Теперь у класса есть своя копия списка; если вызывающая сторона изменяет список, который она передала в качестве аргумента конструктору, ALittleMoreSafe
Экземпляр не будет затронут.
Но история на этом не заканчивается, конечно. Теперь рассмотрим, что в последнем классе есть метод, который возвращает список, полученный в качестве параметра:
class ALittleMoreSafe
{
private final List<X> list;
public ALittleMoreSafe(final List<X> list)
{
list = new ArrayList<X>(list);
}
public List<X> unsafeGetList()
{
return list;
}
}
Ты проиграл! Даже если ваш конструктор безопасен, фактом является то, что вы возвращаете ссылку на свой внутренний список; и вызывающая сторона может изменить список с помощью этой ссылки.
Здесь опять защитная копия может спасти вас, но есть лучшее решение: убедитесь, что возвращаемый вами список неизменен:
public List<X> safeGetList()
{
return Collections.unmodifiableList(list);
}
Любая попытка вызывающей стороны изменить возвращенный список потерпит неудачу.
Итак, история закончилась?
NO.
Это может быть закончено, только если все X
экземпляры неизменны. К сожалению, очень классический и чрезмерно используемый шаблон bean-компонентов не гарантирует этого. Но это другая история.