Чому 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], нам довелося б додати багато додаткових перевірок boudary, (погодьтеся з коментарем Konrads) логіку перетворення та перевантаження методу до нашого коду. Виключення 0 (а може і 1) із дозволених розмірів масиву не економить витрат, воно вимагає додаткових зусиль і негативно впливає на продуктивність.

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

Масив є гарною моделлю даних для вектора (математик, а НЕVector клас!). І звичайно, вектор у математиці може бути нульовим розміром. Що концептуально відрізняється від того, щоб не існувати.


Sidenote - Stringклас, який має видатну обгортку для (char-) масиву . Незмінна Stringматеріалізує поняття порожнього масиву: це порожній String ( "").


2
Я не вірю вашому аргументу обмеження. Java (на відміну, наприклад, від C) вже вимагає перевірки на від’ємні числа. Ця перевірка може бути тривіально адаптована для розміщення 0 (просто змініть >= 0на > 0). Але ви, звичайно, маєте рацію щодо решти, тому додавання цього обмеження не мало б сенсу.
Конрад Рудольф

На мій погляд, аргумент ітерації циклу здається кращим: "for (int k = 0; k <strings.length; k ++) {// something}"
dannyxyz22

2
Ні, це не на мій погляд, оскільки у світі без масивів нульового розміру порожніх рядків (на основі масивів char) просто не існувало б, і тому не було б потреби розглядати порожні масиви у циклах. Цей аргумент ітерації є дуже практичним побічним ефектом. У тому світі масив мав би мати мінімум один запис. (Або два, тому що: навіщо потрібен масив лише для одного предмета?)
Андреас Долк,

Перевірка на від’ємний індекс та занадто високий індекс - це одна і та ж перевірка: від’ємні індекси завжди без
знаків


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) у масиви, і це має сенс лише перетворити порожній список у порожній масив.



4

Ще один випадок, коли масив нульової довжини може бути корисним: Щоб повернути масив, що містить усі елементи у списку:

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

Масив нульової довжини може бути використаний для передачі типу масиву в цей метод. Наприклад:

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

Масив нульової довжини все ще є екземпляром Object, який містить нульові елементи.


2

Одним з випадків, коли я можу подумати, де порожній масив надзвичайно корисний, є використання його замість null у ситуації, коли null не дозволяється. Одним з можливих прикладів цього є BlockingQueue масивів. Що ви хочете зробити, коли ви хочете подати сигнал про закінчення введення стороні читання? Надіслати null здається очевидним вибором, але справа в тому, що BlockingQueue не приймає null. Ви можете обернути свій масив усередині класу 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[]є досить поширеним явищем. Наприклад, для власного кодування, декодування рядків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.