Есть ли неизменная альтернатива примитивным массивам в Java? Создание примитивного массива на final
самом деле не мешает делать что-то вроде
final int[] array = new int[] {0, 1, 2, 3};
array[0] = 42;
Я хочу, чтобы элементы массива были неизменными.
int[]
иnew int[]
НАМНОГО проще печатать, чемList<Integer>
иnew ArrayList<Integer>
? XDОтветы:
Не с примитивными массивами. Вам нужно будет использовать список или другую структуру данных:
источник
Arrays.asList
является неизменяемым. docs.oracle.com/javase/7/docs/api/java/util/… "Возвращает список фиксированного размера, поддерживаемый указанным массивом. (Изменения в возвращенном списке" записывают "в массив.)"Arrays.asList()
действительно, кажется неизменным в том смысле, что вы не можетеadd
илиremove
элементы возвращаемыхjava.util.Arrays.ArrayList
( не путать сjava.util.ArrayList
) - эти операции просто не реализованы. Может быть @mauhiz пытается это сказать? Но, конечно, вы можете изменять существующие элементы с помощью QEDList<> aslist = Arrays.asList(...); aslist.set(index, element)
, поэтому,java.util.Arrays.ArrayList
конечно, это не является неизменным. Добавлен комментарий только для того, чтобы подчеркнуть разницу между результатомasList
и нормойArrayList
Моя рекомендация состоит в том, чтобы не использовать массив или
unmodifiableList
но использовать Guava «s ImmutableList , которая существует для этой цели.источник
Collections.unmodifiableList
достаточно, чтобы сделать List неизменным?Как уже отмечали другие, в Java не может быть неизменных массивов.
Если вам абсолютно необходим метод, который возвращает массив, который не влияет на исходный массив, то вам придется каждый раз клонировать массив:
Очевидно, что это довольно дорого (так как вы будете создавать полную копию каждый раз, когда вызываете геттер), но если вы не можете изменить интерфейс (
List
например, использовать) и не можете рисковать, когда клиент меняет ваши внутренние компоненты, тогда это может быть необходимо.Эта техника называется создание защитной копии.
источник
clone()
илиArrays.copy()
здесь?Есть один способ сделать неизменный массив в Java:
Массивы с 0 элементами (очевидно) не могут быть изменены.
Это действительно может пригодиться, если вы используете
List.toArray
метод для преобразованияList
в массив. Поскольку даже пустой массив занимает некоторую память, вы можете сохранить это выделение памяти, создав постоянный пустой массив и всегда передавая егоtoArray
методу. Этот метод выделяет новый массив , если массив вы передаете не имеет достаточно мест, но если это делает (список пуст), он возвращает массив , который вы прошли, что позволяет повторно использовать этот массив в любое время позвонитьtoArray
по принципу опорожнитьList
.источник
Еще один ответ
источник
На Java-вы можете использовать
List.of(...)
, JavaDoc .Этот метод возвращает неизменный
List
и очень эффективен.источник
Если вам нужен (по соображениям производительности или для экономии памяти) нативный 'int' вместо 'java.lang.Integer', то вам, вероятно, потребуется написать собственный класс-оболочку. В сети есть различные реализации IntArray, но ни одна (я обнаружил) не была неизменной: Koders IntArray , Lucene IntArray . Есть, наверное, другие.
источник
Начиная с Guava 22, из пакета
com.google.common.primitives
вы можете использовать три новых класса, которые занимают меньше места по сравнению сImmutableList
.У них также есть строитель. Пример:
или, если размер известен во время компиляции:
Это еще один способ получить неизменный вид массива для примитивов Java.
источник
Нет, это невозможно. Тем не менее, можно сделать что-то вроде этого:
Это требует использования оберток, и это список, а не массив, но это ближайший к вам.
источник
valueOf()
, об этом позаботится автобокс. ТакжеArrays.asList(0, 2, 3, 4)
было бы гораздо более кратким.valueOf()
использования внутреннего кеша объектов Integer для уменьшения потребления / перезапуска памяти.int
вInteger
хотя; просто нужно быть осторожным, наоборот.В некоторых ситуациях будет проще использовать этот статический метод из библиотеки Google Guava:
List<Integer> Ints.asList(int... backingArray)
Примеры:
List<Integer> x1 = Ints.asList(0, 1, 2, 3)
List<Integer> x1 = Ints.asList(new int[] { 0, 1, 2, 3})
источник
Если вы хотите избежать как изменчивости, так и бокса, выхода из коробки нет. Но вы можете создать класс, который содержит примитивный массив внутри и предоставляет доступ только для чтения к элементам через метод (ы).
источник
Метод of (E ... elements) в Java9 можно использовать для создания неизменяемого списка, используя только строку:
Приведенный выше метод возвращает неизменный список, содержащий произвольное количество элементов. И добавление любого целого числа в этот список приведет к
java.lang.UnsupportedOperationException
исключению. Этот метод также принимает один массив в качестве аргумента.источник
Хотя это правда, что
Collections.unmodifiableList()
работает, иногда у вас может быть большая библиотека с уже определенными методами для возврата массивов (напримерString[]
). Чтобы предотвратить их нарушение, вы можете определить вспомогательные массивы, в которых будут храниться значения:Тестировать:
Не идеально, но по крайней мере у вас есть «псевдо неизменяемые массивы» (с точки зрения класса), и это не нарушит связанный код.
источник
Ну .. массивы полезно передавать как константы (если они были) как параметры вариантов.
источник
int[]
, вызывающая сторона вполне может предположить, что они могут делать с этим массивом то, что они хотят, не затрагивая внутреннюю часть API.