Рассмотрите этот фрагмент кода:
class MyClass{
private List myList;
//...
public List getList(){
return myList;
}
}
Поскольку Java передает ссылки на объект значением, мое понимание то, что любой объектный вызов getList()
получит ссылку на myList
, разрешение этого изменить myList
несмотря на него быть private
. Это корректно?
И, если это корректно, должен я использовать
return new LinkedList(myList);
создать копию и пасовать назад ссылку на копию, а не оригинал, для предотвращения несанкционированного доступа к списку, на который ссылаютсяmyList
?
Я так и делаю. Еще лучше, иногда я возвращаю неизменяемую копию, используя API Collections.
Если вы этого не делаете, ваша ссылка не является приватной. Любой, у кого есть ссылка, может изменить ваше приватное состояние. То же самое справедливо для любой изменяемой ссылки (например, Date).
Это зависит от того, что вы хотите.
Хотите ли вы раскрыть список и сделать так, чтобы люди могли его редактировать?
Или вы хотите позволить людям смотреть на него, но не изменять?
В этом случае нет правильного или неправильного пути. Это просто зависит от ваших потребностей в дизайне.
В некоторых случаях может потребоваться вернуть "необработанный" список вызывающей стороне. Но в целом я считаю, что это плохая практика, поскольку она нарушает инкапсуляцию и, следовательно, против OO. Если вы должны вернуть «необработанный» список, а не копию, он должен быть явно понятен пользователям MyClass.
Да, и у него есть название... "Защитное копирование". Копирование на принимающей стороне также рекомендуется. Как отметил Том, поведение программы гораздо легче предсказать, если коллекция неизменяема. Поэтому, если у вас нет очень веской причины, вы должны использовать неизменяемую коллекцию.
Когда Google Guava станет частью стандартной библиотеки Java (я считаю, что так и должно быть), эта идиома, вероятно, станет предпочтительной:
return ImmutableList.copyOf(someList);
и
void (List someList){
someList = ImmutableList.copyOf(someList);
Это имеет дополнительный бонус производительности, потому что метод copyOf()
проверяет, является ли коллекция уже экземпляром неизменяемой коллекции (instanceof ImmutableList
), и если да, то пропускает копирование.
Я думаю, что шаблон создания частных полей и предоставления средств доступа просто предназначен для инкапсуляции данных. Если вы хотите, чтобы что-то было действительно приватным, не давайте ему методы доступа! Затем вы можете написать другие методы, которые возвращают неизменяемые версии ваших личных данных или их копии.