Возвращение константной ссылки арраиста

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

У меня есть класс, который может быть унаследован, а внутри него есть private ArrayList arr; Таким образом, функция setter в порядке, но функция getter return arr; возвращает ссылку на эту переменную, которая может редактировать любой массив, который Я не хочу, и частные не будут иметь никакого смысла!

В С++ я бы просто return const arr; и возвращал бы постоянную ссылку на переменную.

Мне так нужна переменная, которая не должна быть клонирована или скопирована вручную, потому что есть так много вычислений, которые требуют (ЗАЧИТАЙТЕ ТОЛЬКО переменную) ПОЧЕМУ нет никакой константы, возвращающейся в java???? есть ли способ избежать копирования?

p.s (final ArrayList<Integer> arr;) не является параметром, потому что массив всегда меняет размер или значения элементов.

Если бы я не мог найти исправления, я угрожаю вернуться на С++ или сделать все общедоступным, и вы никогда не получите мое программное обеспечение: D


EDIT: еще один важный вопрос: я прошу что-то нехорошее (техническая инженерия мудрая) Я имею в виду, если бы создатели JAVA не имели ссылки на const (возвращающие только ссылки на чтение), тогда я должен просить что-то, что может быть обрабатывается другим способом. или мой дизайн программы неправильный Я так запутался.

Ответы

Ответ 1

Оберните возвращаемое значение java.util.Collections.unmodifiableList. Он не делает копию данных, но обертывает исходный список и делегирует операции только для чтения в основной список. Операции, которые будут изменять список, будут отклонены во время выполнения через UnsupportedOperationException.

Ваш

return arrayList;

становится

return Collections.unmodifiableList(arrayList);

К сожалению, ограничения, доступные только для чтения, не будут выполняться компилятором. Тем не менее, они будут применяться во время выполнения.

У вас также есть для вас: unmodifiableSet, unmodifiableMap, unmodifiableCollection, unmodifiableSortedSet и unmodifiableSortedMap, И если их недостаточно, вы все равно можете вдохновиться этим общим подходом к дизайну и создать свои собственные классы оболочки только для чтения.

Ответ 2

:) У вас есть несколько вариантов:

  • Не выставляйте getter, предоставляйте только методы, которые разрешены для вызова, например

    public void addToList(Object arg) { this.arr.add(arg);}

  • Возвращаемый неизменяемый объект:

    public List getArr() { return Collections.unmodifiableList(this.arr); }

Ответ 3

Вы также можете использовать Google Guava неизменяемые коллекции. В этом случае вы сохранили ImmutableList в своем поле.

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

Но это прекрасно, когда вы знаете, что List не изменится после построения объекта.

Необязательный пример (список не изменится после построения объекта)

@Immutable
public final class Foo {

    @Nonnull
    private final ImmutableList<String> list;

    public Foo(@Nonnull List<String> list) {
        // you could also compute the appropriate list here
        // before assigning it to the field
        this.list = ImmutableList.copyOf(list);
    }


    public ImmutableList<String> getList() {
        return list;
    }
}

Mutable example (список может быть изменен только с помощью установщика)

public class Foo {

    @Nonnull
    private ImmutableList<String> list = ImmutableList.of();

    public ImmutableList<String> getList() {
        return list;
    }

    public void setList(@Nonnull List<String> list) {
        this.list = ImmutableList.copyOf(list);
    }
}

Примечания

  • Я знаю, что часто рекомендуется, чтобы методы возвращали наиболее общий тип (List в этом случае), но я предпочитаю объявлять возвращаемый тип getter как ImmutableList, потому что он действует как документация (нет необходимости документируйте неизменность возвращаемого списка в Javadoc) и как контракт API. Это, как сказать: "Я гарантирую, чтобы этот список был неизменным, вам не нужно беспокоиться или защищать его". И это очень красноречиво.
  • ImmutableList.copyOf() отлично, поскольку он автоматически отклоняет нулевые списки (бросая NullPointerException). Он также отклоняет нулевые элементы. И он не будет копировать исходный список, если он уже является ImmutableList, который избегает бесполезной реализации объекта.
  • Во втором примере я инициализирую поле пустым ImmutableList, используя ImmutableList.of(), потому что хорошая практика возвращать пустые коллекции вместо нулевых значений (Образец нулевого объекта). Вы можете подумать, что это создает ненужное создание объекта, но ImmutableList.of() фактически возвращает одноэлемент.

Ответ 4

Существует альтернатива немодифицируемому методу. Вы можете просто вернуть копию этого частного массива. Например,

    return your_private_array.clone();

Ну, для этого может быть штраф за исполнение. Но у вас есть интерфейс без изменений (вы все равно возвращаете массив).

Ответ 5

unmodifiableList, безусловно, является ответом.