Почему Java допускает массивы размера 0?

82

Массивы в java имеют фиксированную длину. Почему тогда Java разрешает массивы размера 0?

String[] strings = new String[0];
Роббин
источник

Ответы:

122

Это означает, что он пуст. То есть вы можете перебрать его, как если бы он имел элементы и не получил никакого результата:

for(int k = 0; k < strings.length; k++){
   // something
}

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

Полдень шелк
источник
9
Это также полезно для test(Object... objects)явного вызова функции, когда функция естьtest()
Frithjof
51

Почему Java допускает использование массивов размером 1? Разве не бесполезно заключать одно значение в массив? Разве не было бы достаточно, если бы в Java разрешались только массивы размером 2 или больше?

Да, мы можем передать nullвместо пустого массива и один объект или примитив вместо матрицы размера один.

Но есть веские аргументы против такого ограничения. Мои личные главные аргументы:

Ограничение слишком сложно и не обязательно

Чтобы ограничить массивы размерами [1..INTEGER.MAX_INT], нам пришлось бы добавить множество дополнительных проверок, (согласитесь с комментарием Конрадса) логики преобразования и перегрузок методов в наш код. Исключение 0 (и, возможно, 1) из разрешенных размеров массива не экономит затрат, требует дополнительных усилий и отрицательно сказывается на производительности.

Вектор моделей массива

Массив является хорошей моделью данных для вектора (математик, а неVector класс!). И, конечно же, вектор в математике может быть нулевым. Что концептуально отличается от несуществования.


Sidenote - заметной оберткой для массива (char-) является Stringкласс. Неизменяемый Stringматериализует концепцию пустого массива: это пустая строка ( "").

Андреас Долк
источник
2
Я не верю вашему аргументу о запрете. Java (в отличие, например, от C) уже требует проверки на отрицательные числа. Эта проверка может быть легко адаптирована для размещения 0 (просто измените >= 0на > 0). Но в остальном вы, конечно, правы, поэтому добавление этого ограничения не имело бы смысла.
Конрад Рудольф
На мой взгляд, аргумент итерации цикла кажется лучше: «for (int k = 0; k <strings.length; k ++) {// something}»
dannyxyz22,
2
Нет, на мой взгляд, это не так, потому что в мире без массивов нулевого размера пустые строки (основанные на массивах символов) просто не существовали бы, и поэтому не было бы необходимости рассматривать пустые массивы в циклах. Этот аргумент итерации - очень практичный побочный эффект. В этом мире массив будет иметь как минимум одну запись. (Или два, потому что: зачем нужен массив только для одного элемента?)
Андреас Долк
Проверка на отрицательный индекс и слишком высокий индекс - это одна и та же проверка: отрицательные индексы всегда беззнаковые, не меньше, чем длина массива
Гарольд
26

Иногда гораздо удобнее вернуть массив нулевого размера, чем нулевой.

О Фройнде
источник
9
Это называется паттерном «Нулевой объект».
Александр Дубинский
16

Подумайте об этом (более подробное объяснение ответа Полдня):

public String[] getStrings() {
 if( foo ) {
  return null;
 } else {
  return new String[] {"bar, "baz"};
 }
}

String[] strings = getStrings();
if (strings != null) {
 for (String s : strings) {
  blah(s);
 }
}

Теперь сравните это с этим:

public String[] getStrings() {
 if( foo ) {
  return new String[0];
 } else {
  return new String[] {"bar, "baz"};
 }
}

// the if block is not necessary anymore
String[] strings = getStrings();
for (String s : strings) {
 blah(s);
}

Это (возвращение пустых массивов, а не нулевых значений) на самом деле является лучшей практикой в ​​мире проектирования Java API.

Кроме того, в Java вы можете скрывать списки (например, ArrayList) в массивы, и имеет смысл преобразовывать только пустой список в пустой массив.

βξhrαng
источник
5

Как и C ++, он позволяет более аккуратно обрабатывать данные при отсутствии данных.

Дэн МакГрат
источник
4

Другой случай, когда может быть полезен массив нулевой длины: чтобы вернуть массив, содержащий все элементы в списке:

<T> T[ ] toArray(T[ ] a)

Для передачи типа массива в этот метод можно использовать массив нулевой длины. Например:

ClassA[ ] result = list.toArray(new ClassA[0]);

Массив нулевой длины по-прежнему является экземпляром Object, который содержит нулевые элементы.

Дон Ли
источник
2

Я могу придумать один случай, когда пустой массив чрезвычайно полезен, - это использовать его вместо null в ситуации, когда null не допускается. Одним из возможных примеров этого является BlockingQueue массивов. Что бы вы сделали, когда хотите сигнализировать об окончании ввода читающей стороне? Отправка null кажется очевидным выбором, но дело в том, что BlockingQueue не принимает нули. Вы могли бы обернуть свой массив внутри класса с boolean last;полем типа "", но это своего рода излишество. Отправка пустого (нулевого) массива кажется наиболее разумным выбором.

Сергей Таченов
источник
0

Другой случай, когда полезен массив нулевой длины, - это копирование двумерного массива. Я могу написать:

public int[][] copyArray(int[][] array){
     int[][] newArray = new int[array.length][0];
     for(int i=0;i<array.length;i++){
         newArray[i] = array[i];
     }
     return newArray;

Поскольку каждая ссылка на массив в массиве перезаписывается, инициализация их как ссылок на массивы нулевой длины является наиболее эффективной.

шахматист
источник
0

0-длина byte[]или char[]может представлять пустое поле String, отличное от null. Получение байтов или символов, как массивы из строк ( с использованием getBytes(), getChars()из Stringкласса и т.д.) и наоборот формирования Strings из byte[], char[]является довольно распространенным явлением. Например, для нестандартной кодировки, декодирования строк.

Мадху
источник