Dlaczego Java zezwala na tablice o rozmiarze 0?

82

Tablice w Javie mają stałą długość. Dlaczego więc Java zezwala na tablice o rozmiarze 0?

String[] strings = new String[0];
rabować
źródło

Odpowiedzi:

122

Oznacza to, że jest pusty. Oznacza to, że możesz zapętlić go tak, jakby miał elementy i nie ma żadnego wyniku:

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

Dzięki temu unika się konieczności sprawdzania. Gdyby tablica, o której mowa null, miałaby miejsce, wystąpiłby wyjątek, ale w tym przypadku po prostu nic nie robi, co może być właściwe.

Noon Silk
źródło
9
Jest również przydatny do wywoływania funkcji test(Object... objects)jawnie, gdy istnieje funkcjatest()
Frithjof
51

Dlaczego Java zezwala na tablice o rozmiarze 1? Czy nie jest całkiem bezużyteczne zawijanie pojedynczej wartości w tablicy? Czy nie wystarczyłoby, gdyby Java dopuszczała tylko tablice o rozmiarze 2 lub większym?

Tak, nullzamiast niej możemy przekazać pustą tablicę i pojedynczy obiekt lub prymityw zamiast macierzy o rozmiarze jeden.

Ale jest kilka dobrych argumentów przeciwko takiemu ograniczeniu. Moje osobiste najważniejsze argumenty:

Ograniczenie jest zbyt skomplikowane i nie jest konieczne

Aby ograniczyć tablice do rozmiarów [1..INTEGER.MAX_INT], musielibyśmy dodać wiele dodatkowych sprawdzeń boudarowych, (zgadzam się z komentarzem Konradsa ) logikę konwersji i przeciążenia metod w naszym kodzie. Wyłączenie 0 (a może 1) z dozwolonych rozmiarów macierzy nie oszczędza kosztów, wymaga dodatkowego wysiłku i ma negatywny wpływ na wydajność.

Wektor modeli macierzy

Tablica jest dobrym modelem danych dla wektora (matematyka, nieVector klasy!). Oczywiście wektor w matematyce może być zerowymiarowy. Który koncepcyjnie różni się od bycia nieistniejącym.


Uwaga dodatkowa - wyróżniającym się opakowaniem dla tablicy (znaków) jest Stringklasa. Niezmienna Stringmaterializuje koncepcję pustej tablicy: jest to pusty String ( "").

Andreas Dolk
źródło
2
Nie wierzę w twój argument dotyczący ograniczenia. Java (w przeciwieństwie np. C) już wymaga sprawdzenia liczb ujemnych. To sprawdzenie można by w prosty sposób dostosować, aby pomieściło 0 (wystarczy zmienić >= 0na > 0). Ale oczywiście masz rację co do reszty, więc dodanie tego ograniczenia nie miałoby sensu.
Konrad Rudolph
Moim zdaniem argument iteracji pętli wydaje się lepszy: "for (int k = 0; k <strings.length; k ++) {// coś}"
dannyxyz22
2
Nie, moim zdaniem nie, ponieważ w świecie bez tablic o rozmiarze zerowym puste łańcuchy (oparte na tablicach char) po prostu nie istniałyby, więc nie byłoby potrzeby rozważania pustych tablic w pętlach. Ten argument iteracji jest bardzo praktycznym efektem ubocznym. W tym świecie tablica miałaby co najmniej jeden wpis. (Lub dwa, ponieważ: po co mi tablica tylko dla jednego elementu?)
Andreas Dolk,
Sprawdzenie indeksu ujemnego i zbyt wysokiego jest tym samym sprawdzeniem: indeksy ujemne są zawsze bez znaku-nie mniej-niż długość tablicy
harold
26

Czasami bardziej przyjazne jest zwrócenie tablicy o rozmiarze zerowym niż null.

Na Freunda
źródło
9
Nazywa się to wzorcem „Obiekt zerowy”.
Aleksandr Dubinsky
16

Rozważ to (bardziej szczegółowe wyjaśnienie odpowiedzi Noona):

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);
 }
}

Teraz porównaj to z tym:

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);
}

To (zwracanie pustych tablic zamiast wartości null) jest w rzeczywistości najlepszą praktyką w świecie projektowania Java API.

Poza tym w Javie możesz zamieniać listy (np. ArrayList) na tablice i sensowne jest tylko przekonwertowanie pustej listy na pustą tablicę.

βξhrαng
źródło
5

Podobnie jak C ++, pozwala na czystszą obsługę, gdy nie ma danych.

Dan McGrath
źródło
4

Inny przypadek, w którym tablica o zerowej długości może być przydatna: Aby zwrócić tablicę zawierającą wszystkie elementy na liście:

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

Tablica o zerowej długości może służyć do przekazywania typu tablicy do tej metody. Na przykład:

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

Tablica o zerowej długości jest nadal instancją Object, która zawiera zero elementów.

Don Li
źródło
2

Jednym z przypadków, o których mogę pomyśleć, w których pusta tablica jest niezwykle przydatna, jest użycie jej zamiast wartości null w sytuacji, gdy wartość null nie jest dozwolona. Jednym z możliwych przykładów jest BlockingQueue tablic. Gdy chcesz zasygnalizować koniec wprowadzania do strony odczytu, co byś zrobił? Wysłanie wartości null wydaje się oczywistym wyborem, ale problem polega na tym, że BlockingQueue nie akceptuje wartości null. Możesz umieścić swoją tablicę wewnątrz klasy z boolean last;polem typu " ", ale to trochę przesada. Wysłanie pustej tablicy (o rozmiarze zerowym) wydaje się najbardziej rozsądnym wyborem.

Siergiej Tachenov
źródło
0

Innym przypadkiem, gdy tablica o zerowej długości jest przydatna, jest kopiowanie tablicy dwuwymiarowej. Umiem pisać:

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;

Ponieważ każde odwołanie do tablicy w tablicy jest nadpisywane, inicjowanie ich jako odniesień do tablic o zerowej długości jest najbardziej wydajne.

programista szachowy
źródło
0

Długość 0 byte[]lub char[]może reprezentować pusty String, który różni się od null. Pierwsze bajtów lub znaków, jak tablice z łańcuchów (stosując getBytes(), getChars()w Stringklasie itp) i vice versa formowania Stringsz byte[], char[]jest dość powszechne. Na przykład w celu niestandardowego kodowania dekodowanie ciągów.

Madhu
źródło