2013-05-26 14 views
5

Właśnie sprawdzałem niektóre pytania OCJP i natknąłem się na tę różnicę podczas inicjalizacji i wyjątków tablicy String.Tablica napisów bez początkowego rozmiaru daje wyjątek wskaźnika pustego

Case 1

try { 
     String[][] b = new String[10][10];//1 
     System.out.println(b[0][0]);//2 
    } catch (Exception e) { 
     System.out.println("Exception during array 'b' initialization"); 
     e.printStackTrace(); 
    } 

Case 2

try { 
     String[][] a = new String[10][];//3 
     System.out.println(a[0][0]);//4 
    } catch (Exception e) { 
     System.out.println("Exception during array 'a' initialization"); 
     e.printStackTrace(); 
    } 

Linia 2 nie rzuca żadnego wyjątku natomiast linia 4 rzuca wyjątku null pointer. Jednak linia 2 wyprowadza wartość jako null.

Czy Java ma różnicę w wartościach domyślnych dla inicjalizacji, gdy określono rozmiar tablicy, a kiedy nie?

Odpowiedz

5

Ustawia typ a, jako tablicy tablic:

String[][] a 

Kiedy piszesz

String[][] a = new String[10][]; 

zainicjować tablicę zewnętrznego, ale nie tworzyć wewnętrzne tablice, więc że a[0] jest null.

Kiedy piszesz

String[][] b = new String[10][10]; 

środowisko wykonawcze tworzy również wewnętrznych tablic. Jest opisany here in the specification:

W czasie wykonywania oceny wyrazem tworzenia tablicy zachowuje się jak następująco:

przypadku braku wyrażenia wymiarowe, to nie musi być tablicą inicjator.

Nowo przydzielona tablica zostanie zainicjowana wartościami podanymi przez inicjatora macierzy, jak opisano w §10.6.

Wartość inicjatora macierzy staje się wartością wyrażenia kreacji tablicy .

W przeciwnym razie, nie ma initializer array, oraz:

pierwsze, wyrażenia wymiarowe są oceniane, od lewej do prawej. Jeśli dowolne wartości oceny wyrażenia zakończą się nagle, wyrażenia do z prawej strony nie zostaną ocenione.

Następnie sprawdzane są wartości wyrażeń wymiaru. Jeśli wartość dowolnego wyrażenia DimExpr jest mniejsza od zera, generowany jest wyjątek NegativeArraySizeEx: .

Następnie, miejsce jest przydzielane dla nowej tablicy. Jeśli nie ma wystarczającej ilości miejsca na przydzielenie tablicy, wyrażenie ekspresu do tworzenia macierzy kończy się nagle, rzucając OutOfMemoryError.

Następnie, jeśli pojawi się pojedynczy DimExpr, jednowymiarowa tablica zostanie utworzona o określonej długości, a każdy składnik tablicy jest zainicjalizowany do wartości domyślnej (§4.12.5).

W przeciwnym razie, jeśli pojawi się n wyrażeń DimExpr, tworzenie macierzy skutecznie wykonuje zestaw zagnieżdżonych pętli o głębokości n-1, aby utworzyć domyślne macierze tablic o wartości .

Tablica wielowymiarowa nie musi mieć tablic o tej samej długości na poziomie na każdym poziomie.

+0

'i każdy składnik tablicy jest inicjalizowany do wartości domyślnej' , więc linia 3 powinna przypisać 10 'tablice 1-D' i przypisać' null' jako wartość do każdego z jego elementów, prawda? Tak samo jak w przypadku linii 1. Czy mam rację? – redDevil

+1

Przypisuje pustą wartość 'a [0]', 'a [1]', itd. Podczas gdy linia 1 przypisuje wartość null do 'b [0] [0]', 'b [0] [1]' itd. –

1
String[][] a = new String[3][]; 

odpowiada:

String[] a1 = null; 
String[] a2 = null; 
String[] a3 = null; 
String[][] a = {a1, a2, a3}; 

i a[0][0] jest podobny do a1[0] który generuje NPE.


Masz dwie możliwości:

  • Albo określają tablicę jako:
String[][] a = new String[3][3]; 
  • lub tworzyć nowe tablice wewnątrz a:
a[0] = new String[2]; 
a[1] = new String[4]; 
a[2] = new String[3]; 

Należy pamiętać, że korzystanie z tego drugiego podejścia będzie można mieć różne rozmiary dla wewnętrznych tablic.

1

Dobre odkrycie. Podczas inicjalizacji tablicy 2D z obu parametrów, co się dzieje:

String[][] a = new String[5][5] 

2D Array with both bounds

Ale kiedy ty nie określić drugi związany, co się dzieje:

String[][] a = new String[5][]; 

2D Array with no inner bound

W linii 4 otrzymasz dokładny wyjątek NullPointerException, ponieważ:

String[][] a = new String[10][]; 
System.out.println(a[0][0]); // << a[0] is null! 

Ale dlaczego potrzebujesz tego zachowania? To całkiem proste. Dotyczy to przypadków, w których każdy element w dwuwymiarowej tablicy może mieć różną liczbę elementów. Potencjał przypadek użycia scenariusz:

enter image description here

I są całkiem dobre przypadki użycia dla tego rodzaju zachowań, takich jak kolejek priorytetowych (każdy priorytet może mieć różną liczbę elementów w kolejce), stół Hash (część z przelewem) itp.

Powiązane problemy