2010-07-11 2 views
8

Рассмотрим следующий фрагмент кода:Лучшая практика для Возвратившись Ссылки на объект

class MyClass{ 
    private List myList; 
    //... 
    public List getList(){ 
     return myList; 
    } 
} 

Как Java передает ссылки на объект по значению, я понимаю, что любой объект вызова getList() получит ссылку на myList, позволяя изменять myList несмотря это private. Это верно?

И, если это правильно, я должен использовать

return new LinkedList(myList); 

, чтобы создать копию и передать обратно ссылку на копию, а не оригинал, в целях предотвращения несанкционированного доступа к списку ссылочного по myList?

+2

технически, никакой внешний клиент не сможет изменить значение поля myList в вашем классе. Он всегда будет дескриптором/ссылкой на List, ссылаясь на список, в который его установил некоторый код внутри MyClass.Внешний клиент сможет изменить содержимое этого списка. –

+0

Да, это то, что я имел в виду, но получил немного неряшливо с моим объяснением. Я отредактирую его – chrisbunney

+0

+1 Miro A для правильного уточнения. И да, ваше решение, создав копию списка, является правильным (для чего вы хотите достичь). – xagyg

ответ

9

Я это делаю. Еще лучше, иногда я возвращаю неизменяемую копию, используя API коллекций.

Если вы этого не сделаете, ваша ссылка не является частной. Любой, у кого есть ссылка, может изменить ваше личное состояние. То же самое верно для любой изменяемой ссылки (например, Date).

+3

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

2

Это зависит от того, что вы хотите.

Вы хотите раскрыть список и сделать так, чтобы люди могли его редактировать?

Или вы хотите, чтобы люди смотрели на него, но не изменяли его?

В этом случае нет правильного или неправильного пути. Это зависит от ваших потребностей в дизайне.

+0

Итак, если ваш дизайн диктует атрибуту, имеет личную видимость, вы должны вернуть копию объекта, а не просто ссылку, чтобы убедиться, что он остается инкапсулированным. – chrisbunney

+0

@chris. Если вы создаете требует, чтобы люди не могли изменить ваш список, а затем передать копию. В противном случае передайте исходную ссылку. – jjnguy

+1

Да, извините, это был риторический комментарий, я понял ваш ответ;) – chrisbunney

1

Могут быть случаи, когда нужно было бы вернуть «сырой» список вызывающему. Но в целом, я думаю, что это плохая практика, так как она разрушает инкапсуляцию и, следовательно, против OO. Если вы должны вернуть «необработанный» список, а не копию, он должен быть явно ясен пользователям MyClass.

0

Да, и у него есть имя .. «Оборонительная копия». Также рекомендуется копирование на приемной стороне. Как Tom has noted, поведение программы намного проще предсказать, если коллекция является неизменной. Поэтому, если у вас нет веских оснований, вы должны использовать неизменяемую коллекцию.

Когда Google Guava становится частью стандартной библиотеки Java (я полностью думаю, что это должно быть), то это, вероятно, станет предпочтительным идиома:

return ImmutableList.copyOf(someList); 

и

void (List someList){ 
    someList = ImmutableList.copyOf(someList); 

Это имеет дополнительный бонус поскольку метод copyOf() проверяет, является ли коллекция уже экземпляром неизменяемой коллекции (instanceof ImmutableList), и если да, то пропускает копирование.

1

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

Смежные вопросы