Масиви в Java мають фіксовану довжину. Чому Java тоді дозволяє масиви розміром 0?
String[] strings = new String[0];
Відповіді:
Це означає, що він порожній. Тобто ви можете прокручувати його так, ніби в ньому є елементи і результату не відбувається:
for(int k = 0; k < strings.length; k++){
// something
}
Тим самим уникнувши необхідності перевірки. Якби масив, про який йде мова null
, стався виняток, але в цьому випадку він просто не робить нічого, що може бути доречним.
Чому Java дозволяє масиви розміром 1? Чи не марно обертати одне значення в масив? Чи не буде достатнім, якби Java дозволяла лише масиви розміром 2 або більше?
Так, ми можемо передавати null
замість порожнього масиву і один об’єкт або примітив замість матриці розміру один.
Але є кілька вагомих аргументів проти такого обмеження. Мої особисті основні аргументи:
Обмеження занадто складне і насправді не потрібне
Щоб обмежити масиви розмірами [1..INTEGER.MAX_INT], нам довелося б додати багато додаткових перевірок boudary, (погодьтеся з коментарем Konrads) логіку перетворення та перевантаження методу до нашого коду. Виключення 0 (а може і 1) із дозволених розмірів масиву не економить витрат, воно вимагає додаткових зусиль і негативно впливає на продуктивність.
Масив моделей вектор
Масив є гарною моделлю даних для вектора (математик, а НЕVector
клас!). І звичайно, вектор у математиці може бути нульовим розміром. Що концептуально відрізняється від того, щоб не існувати.
Sidenote - String
клас, який має видатну обгортку для (char-) масиву . Незмінна String
матеріалізує поняття порожнього масиву: це порожній String ( ""
).
>= 0
на > 0
). Але ви, звичайно, маєте рацію щодо решти, тому додавання цього обмеження не мало б сенсу.
Іноді набагато зручніше повертати масив нульового розміру, ніж нуль.
Розгляньте це (більш детальне пояснення відповіді Полудня):
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) у масиви, і це має сенс лише перетворити порожній список у порожній масив.
Так само, як і в C ++, він забезпечує більш чітку обробку, коли немає даних.
Ще один випадок, коли масив нульової довжини може бути корисним: Щоб повернути масив, що містить усі елементи у списку:
<T> T[ ] toArray(T[ ] a)
Масив нульової довжини може бути використаний для передачі типу масиву в цей метод. Наприклад:
ClassA[ ] result = list.toArray(new ClassA[0]);
Масив нульової довжини все ще є екземпляром Object, який містить нульові елементи.
Одним з випадків, коли я можу подумати, де порожній масив надзвичайно корисний, є використання його замість null у ситуації, коли null не дозволяється. Одним з можливих прикладів цього є BlockingQueue масивів. Що ви хочете зробити, коли ви хочете подати сигнал про закінчення введення стороні читання? Надіслати null здається очевидним вибором, але справа в тому, що BlockingQueue не приймає null. Ви можете обернути свій масив усередині класу boolean last;
полем типу " ", але це надмірно. Надсилання порожнього (нульового) масиву здається найбільш розумним вибором.
Інший випадок, коли масив нульової довжини корисний, - це копіювання двовимірного масиву. Я можу написати:
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 byte[]
або char[]
може представляти порожню String
, яка відрізняється від null
. Отримання байтів або символів, як масиви з рядків ( з використанням getBytes()
, getChars()
з String
класу і т.д.) і навпаки формування String
s з byte[]
, char[]
є досить поширеним явищем. Наприклад, для власного кодування, декодування рядків.
test(Object... objects)
явної, коли функція єtest()