Co to jest wyjątek NullPointerException i jak to naprawić?
Co to są wyjątki o zerowym wskaźniku ( java.lang.NullPointerException
) i co je powoduje?
Jakich metod / narzędzi można użyć do określenia przyczyny, aby zapobiec przedwczesnemu zakończeniu programu przez wyjątek?
Odpowiedzi
Kiedy deklarujesz zmienną odniesienia (tj. Obiekt), tak naprawdę tworzysz wskaźnik do obiektu. Weź pod uwagę następujący kod, w którym deklarujesz zmienną typu pierwotnego int
:
int x;
x = 10;
W tym przykładzie zmienną x
jest an, int
a Java zainicjuje ją 0
za Ciebie. Kiedy przypiszesz mu wartość 10
w drugiej linii, twoja wartość 10
zostanie zapisana w lokalizacji pamięci, do której odwołuje się x
.
Ale kiedy próbujesz zadeklarować typ referencyjny , dzieje się coś innego. Weź następujący kod:
Integer num;
num = new Integer(10);
Pierwsza linia deklaruje zmienną o nazwie num
, ale w rzeczywistości nie zawiera jeszcze wartości pierwotnej. Zamiast tego zawiera wskaźnik (ponieważ typ jest Integer
typem referencyjnym). Ponieważ nie powiedziałeś jeszcze, na co wskazać, Java ustawia to na null
, co oznacza „ Nie wskazuję na nic ”.
W drugim wierszu new
słowo kluczowe służy do tworzenia instancji (lub tworzenia) obiektu typu Integer
, a zmienna wskaźnikowa num
jest przypisywana do tego Integer
obiektu.
NullPointerException
Występuje podczas zadeklarować zmienną, ale nie utworzyć obiekt i przypisać ją do zmiennej przed próbują wykorzystać zawartość zmiennej (tzw wyłuskania ). Więc wskazujesz na coś, co w rzeczywistości nie istnieje.
Wyłuskiwanie danych zwykle ma miejsce podczas korzystania .
z dostępu do metody lub pola albo używania [
do indeksowania tablicy.
Jeśli spróbujesz num
usunąć odwołanie PRZED utworzeniem obiektu, otrzymasz plik NullPointerException
. W najbardziej trywialnych przypadkach kompilator wychwyci problem i poinformuje Cię, że " num may not have been initialized
," ale czasami możesz napisać kod, który nie tworzy bezpośrednio obiektu.
Na przykład możesz mieć następującą metodę:
public void doSomething(SomeObject obj) {
//do something to obj, assumes obj is not null
obj.myMethod();
}
W takim przypadku nie tworzysz obiektu obj
, ale raczej zakładasz, że został on utworzony przed doSomething()
wywołaniem metody. Uwaga, możliwe jest wywołanie metody w następujący sposób:
doSomething(null);
W takim przypadku obj
jest null
, a instrukcja obj.myMethod()
wyrzuci plik NullPointerException
.
Jeśli metoda ma na celu zrobienie czegoś z przekazanym obiektem, tak jak robi to powyższa metoda, należy zgłosić ten NullPointerException
błąd, ponieważ jest to błąd programisty, a programista będzie potrzebował tych informacji do celów debugowania.
Oprócz NullPointerException
s wyrzucanych w wyniku logiki metody, możesz również sprawdzić argumenty metody dla null
wartości i jawnie zgłosić NPE, dodając coś podobnego do następującego na początku metody:
//Throws an NPE with a custom error message if obj is null
Objects.requireNonNull(obj, "obj must not be null");
Zwróć uwagę, że dobrze jest wyraźnie wskazać w komunikacie o błędzie, który obiekt nie może być null
. Zaletą przeprowadzania walidacji w ten sposób jest to, że 1) możesz zwrócić własne wyraźniejsze komunikaty o błędach i 2) w przypadku pozostałej części metody wiesz, że jeśli nie obj
zostanie ponownie przypisana, nie jest ona zerowa i można ją bezpiecznie usunąć.
Alternatywnie mogą wystąpić przypadki, w których celem metody nie jest wyłącznie operowanie na przekazanym obiekcie, a zatem parametr zerowy może być akceptowany. W takim przypadku należałoby sprawdzić parametr zerowy i zachowywać się inaczej. Powinieneś to również wyjaśnić w dokumentacji. Na przykład doSomething()
można zapisać jako:
/**
* @param obj An optional foo for ____. May be null, in which case
* the result will be ____.
*/
public void doSomething(SomeObject obj) {
if(obj == null) {
//do something
} else {
//do something else
}
}
Wreszcie, jak wskazać wyjątek i przyczynę za pomocą śledzenia stosu
Jakich metod / narzędzi można użyć do określenia przyczyny, aby zapobiec przedwczesnemu zakończeniu programu przez wyjątek?
Sonar z funkcją wyszukiwania błędów może wykryć NPE. Czy sonar może dynamicznie przechwytywać wyjątki wskaźnika zerowego spowodowane przez maszynę JVM
Teraz Java 14 dodała nową funkcję języka, aby pokazać główną przyczynę NullPointerException. Ta funkcja języka jest częścią komercyjnej maszyny JVM firmy SAP od 2006 r. Poniżej znajdują się 2 minuty czytania, aby zrozumieć tę niesamowitą funkcję języka.
https://jfeatures.com/blog/NullPointerException
W java 14 poniżej znajduje się przykładowy komunikat o wyjątku NullPointerException:
w wątku „main” java.lang.NullPointerException: Nie można wywołać „java.util.List.size ()”, ponieważ „list” ma wartość null
NullPointerException
s są wyjątkami, które występują, gdy próbujesz użyć odwołania, które nie wskazuje na żadną lokalizację w pamięci (null), tak jakby odwoływało się do obiektu. Wywołanie metody w odwołaniu o wartości null lub próba uzyskania dostępu do pola odwołania o wartości null spowoduje wyzwolenie NullPointerException
. Są to najczęstsze, ale inne sposoby są wymienione na stronie NullPointerExceptionjavadoc.
Prawdopodobnie najszybszym przykładowym kodem, jaki mógłbym wymyślić, aby zilustrować a, NullPointerException
byłby:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
W pierwszym wierszu wewnątrz main
jawnie ustawiam Object
odniesienie obj
równe null
. Oznacza to, że mam odniesienie, ale nie wskazuje ono na żaden obiekt. Następnie próbuję traktować odniesienie tak, jakby wskazywało na obiekt, wywołując na nim metodę. Powoduje to, NullPointerException
ponieważ nie ma kodu do wykonania w lokalizacji, na którą wskazuje odwołanie.
(Jest to kwestia techniczna, ale myślę, że warto o tym wspomnieć: odniesienie wskazujące na wartość null to nie to samo, co wskaźnik C, który wskazuje na nieprawidłowe miejsce w pamięci. Wskaźnik zerowy dosłownie nie wskazuje nigdzie , co jest nieco inne niż wskazując lokalizację, która okazała się nieprawidłowa.)
Co to jest wyjątek NullPointerException?
Dobrym miejscem do rozpoczęcia jest JavaDocs . Obejmują to:
Zgłaszane, gdy aplikacja próbuje użyć wartości null w przypadku, gdy obiekt jest wymagany. Obejmują one:
- Wywołanie metody instancji obiektu o wartości null.
- Dostęp do pola obiektu zerowego lub modyfikowanie go.
- Przyjmowanie długości null tak, jakby była tablicą.
- Uzyskiwanie dostępu lub modyfikowanie przedziałów wartości null tak, jakby to była tablica.
- Rzucanie null tak, jakby to była wartość rzucana.
Aplikacje powinny zgłaszać wystąpienia tej klasy, aby wskazać inne nielegalne zastosowania obiektu o wartości null.
Jest również przypadek, że jeśli spróbujesz użyć odwołania zerowego z synchronized
, spowoduje to również zgłoszenie tego wyjątku, zgodnie z JLS :
SynchronizedStatement: synchronized ( Expression ) Block
- W przeciwnym razie, jeśli wartość Expression jest null,
NullPointerException
zostanie zgłoszony a.
Jak to naprawić?
Więc masz NullPointerException
. Jak to naprawić? Weźmy prosty przykład, który rzuca NullPointerException
:
public class Printer {
private String name;
public void setName(String name) {
this.name = name;
}
public void print() {
printString(name);
}
private void printString(String s) {
System.out.println(s + " (" + s.length() + ")");
}
public static void main(String[] args) {
Printer printer = new Printer();
printer.print();
}
}
Zidentyfikuj wartości null
Pierwszym krokiem jest dokładne określenie, które wartości powodują wyjątek . W tym celu musimy przeprowadzić debugowanie. Ważne jest, aby nauczyć się czytać ślad stosu . Dzięki temu dowiesz się, gdzie został zgłoszony wyjątek:
Exception in thread "main" java.lang.NullPointerException
at Printer.printString(Printer.java:13)
at Printer.print(Printer.java:9)
at Printer.main(Printer.java:19)
Tutaj widzimy, że wyjątek jest zgłaszany w linii 13. (w printString
metodzie). Spójrz na wiersz i sprawdź, które wartości są puste, dodając instrukcje rejestrowania lub używając debugera . Dowiadujemy się, że s
jest null, a wywołanie length
metody na nim zgłasza wyjątek. Widzimy, że program przestaje rzucać wyjątek, gdy s.length()
zostanie usunięty z metody.
Prześledź, skąd pochodzą te wartości
Następnie sprawdź, skąd pochodzi ta wartość. Podążając za obiektami wywołującymi metodę, widzimy, że s
jest ona przekazywana za printString(name)
pomocą print()
metody i this.name
ma wartość null.
Prześledź, gdzie należy ustawić te wartości
Gdzie jest this.name
ustawione? W setName(String)
metodzie. Po dłuższym debugowaniu widać, że ta metoda w ogóle nie jest wywoływana. Jeśli metoda została wywołana, sprawdź kolejność wywoływania tych metod, a metoda set nie jest wywoływana po metodzie print.
To wystarczy, aby dać nam rozwiązanie: dodaj połączenie printer.setName()
przed rozmową printer.print()
.
Inne poprawki
Zmienna może mieć wartość domyślną (i setName
może uniemożliwić ustawienie jej na null):
private String name = "";
Każda metoda print
lub printString
może sprawdzić wartość null , na przykład:
printString((name == null) ? "" : name);
Lub możesz zaprojektować klasę tak, aby name
zawsze miała wartość różną od null :
public class Printer {
private final String name;
public Printer(String name) {
this.name = Objects.requireNonNull(name);
}
public void print() {
printString(name);
}
private void printString(String s) {
System.out.println(s + " (" + s.length() + ")");
}
public static void main(String[] args) {
Printer printer = new Printer("123");
printer.print();
}
}
Zobacz też:
- Unikasz instrukcji „! = Null” w Javie?
Nadal nie mogę znaleźć problemu
Jeśli próbowałeś debugować problem i nadal nie masz rozwiązania, możesz zadać pytanie, aby uzyskać dodatkową pomoc, ale pamiętaj, aby uwzględnić to, co do tej pory próbowałeś. Jako minimum, umieść w pytaniu ślad stosu i zaznacz w kodzie ważne numery wierszy . Spróbuj też najpierw uprościć kod (patrz SSCCE ).
Pytanie: Co powoduje NullPointerException
(NPE)?
Jak powinieneś wiedzieć, typy Java są podzielone na prymitywnych typów ( boolean
, int
etc.) i typów referencyjnych . Typy odwołań w Javie pozwalają na użycie specjalnej wartości, null
która w Javie oznacza „brak obiektu”.
A NullPointerException
jest wyrzucane w czasie wykonywania za każdym razem, gdy twój program próbuje użyć a null
tak, jakby był prawdziwym odniesieniem. Na przykład, jeśli napiszesz to:
public class Test {
public static void main(String[] args) {
String foo = null;
int length = foo.length(); // HERE
}
}
instrukcja oznaczona „TUTAJ” spowoduje próbę uruchomienia length()
metody na null
referencji, co spowoduje wyświetlenie pliku NullPointerException
.
Istnieje wiele sposobów użycia null
wartości, która spowoduje rozszerzenie pliku NullPointerException
. W rzeczywistości jedyne rzeczy, które możesz zrobić z a null
bez powodowania NPE, to:
- przypisać go do zmiennej odniesienia lub odczytać ze zmiennej odniesienia,
- przypisać go do elementu tablicy lub odczytać z elementu tablicy (pod warunkiem, że samo odwołanie do tablicy ma wartość różną od null!),
- przekazać go jako parametr lub zwrócić jako wynik lub
- przetestować go przy użyciu
==
lub!=
operatorów, lubinstanceof
.
Pytanie: Jak odczytać ślad stosu NPE?
Załóżmy, że kompiluję i uruchamiam powyższy program:
$ javac Test.java $ java Test
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:4)
$
Pierwsza obserwacja: kompilacja się udała! Problem w programie NIE jest błędem kompilacji. To jest błąd wykonania . (Niektóre IDE mogą ostrzegać, że twój program zawsze zgłosi wyjątek ... ale standardowy javac
kompilator tego nie robi).
Druga uwaga: kiedy uruchamiam program, wypisuje on dwie linijki „gobbledy-gook”. ŹLE!! To nie jest gobbledy-gook. Jest to ślad stosu ... i dostarcza ważnych informacji , które pomogą ci wyśledzić błąd w kodzie, jeśli poświęcisz trochę czasu na jego dokładne przeczytanie.
Spójrzmy więc, co mówi:
Exception in thread "main" java.lang.NullPointerException
Pierwsza linia śladu stosu zawiera kilka informacji:
- Podaje nazwę wątku Java, w którym został zgłoszony wyjątek. W przypadku prostego programu z jednym wątkiem (takiego jak ten) będzie to „główny”. Przejdźmy dalej ...
- Podaje pełną nazwę zgłoszonego wyjątku; tj
java.lang.NullPointerException
. - Jeśli wyjątek ma skojarzony komunikat o błędzie, zostanie on wyprowadzony po nazwie wyjątku.
NullPointerException
jest pod tym względem nietypowe, ponieważ rzadko pojawia się komunikat o błędzie.
Druga linia jest najważniejsza w diagnozowaniu NPE.
at Test.main(Test.java:4)
To mówi nam o kilku rzeczach:
- „at Test.main” mówi, że byliśmy w
main
metodzieTest
klasy. - „Test.java:4” podaje nazwę pliku źródłowego klasy ORAZ informuje nas, że instrukcja, w której to się stało, znajduje się w linii 4 pliku.
Jeśli policzysz wiersze w powyższym pliku, wiersz 4 to ten, który oznaczyłem komentarzem „TUTAJ”.
Zauważ, że w bardziej skomplikowanym przykładzie, w śladzie stosu NPE będzie dużo linii. Ale możesz być pewien, że druga linia (pierwsza linia „at”) powie Ci, gdzie wyrzucono NPE 1 .
Krótko mówiąc, ślad stosu pokaże nam jednoznacznie, która instrukcja programu wyrzuciła NPE.
1 - Nie do końca prawda. Istnieją rzeczy zwane wyjątkami zagnieżdżonymi ...
Pytanie: Jak znaleźć przyczynę wyjątku NPE w moim kodzie?
To jest najtrudniejsza część. Krótką odpowiedzią jest zastosowanie logicznego wnioskowania do dowodów dostarczonych przez ślad stosu, kod źródłowy i odpowiednią dokumentację API.
Zilustrujmy najpierw prostym przykładem (powyżej). Zaczynamy od przyjrzenia się linii, o której ślad stosu poinformował nas, że wystąpił NPE:
int length = foo.length(); // HERE
Jak to może rzucić NPE?
W rzeczywistości jest tylko jeden sposób: może się to zdarzyć tylko wtedy, gdy foo
ma wartość null
. Następnie próbujemy uruchomić tę length()
metodę null
i ... BANG!
Ale (słyszę, jak mówisz) co by było, gdyby NPE został wyrzucony wewnątrz length()
wywołania metody?
Cóż, gdyby tak się stało, ślad stosu wyglądałby inaczej. Pierwsza linia „at” powie, że wyjątek został zgłoszony w jakiejś linii w java.lang.String
klasie, a linia 4 Test.java
będzie drugą linią „at”.
Więc skąd to się null
wzięło? W tym przypadku jest to oczywiste i oczywiste jest, co musimy zrobić, aby to naprawić. (Przypisz niezerową wartość do foo
.)
OK, spróbujmy więc nieco trudniejszego przykładu. Będzie to wymagało pewnych logicznych dedukcji .
public class Test {
private static String[] foo = new String[2];
private static int test(String[] bar, int pos) {
return bar[pos].length();
}
public static void main(String[] args) {
int length = test(foo, 1);
}
}
$ javac Test.java
$ java Test Exception in thread "main" java.lang.NullPointerException at Test.test(Test.java:6) at Test.main(Test.java:10) $
Mamy więc teraz dwie linie „na”. Pierwsza dotyczy tej linii:
return args[pos].length();
a druga dotyczy tej linii:
int length = test(foo, 1);
Patrząc na pierwszą linię, jak to mogło spowodować wystąpienie NPE? Istnieją dwa sposoby:
- Jeśli wartość
bar
to,null
tobar[pos]
wyrzuci NPE. - Jeśli wartość
bar[pos]
to,null
to wywołanielength()
jej spowoduje zgłoszenie NPE.
Następnie musimy dowiedzieć się, który z tych scenariuszy wyjaśnia, co się właściwie dzieje. Zaczniemy od zbadania pierwszego:
Skąd się bar
bierze? Jest to parametr test
wywołania metody i jeśli spojrzymy na to, jak test
została wywołana, zobaczymy, że pochodzi ona ze foo
zmiennej statycznej. Ponadto możemy wyraźnie zobaczyć, że zainicjowaliśmy foo
wartość różną od null. To wystarczy, aby wstępnie odrzucić to wyjaśnienie. (Teoretycznie coś innego mogłoby się zmienić foo
na null
... ale tak się nie dzieje.)
A co z naszym drugim scenariuszem? Cóż, widzimy, że pos
to znaczy 1
, więc to znaczy, że tak foo[1]
musi być null
. czy to możliwe?
Rzeczywiście jest! I to jest problem. Kiedy inicjalizujemy w ten sposób:
private static String[] foo = new String[2];
alokujemy a String[]
z dwoma elementami, które są inicjalizowanenull
. Po tym nie zmieniliśmy zawartości foo
... tak foo[1]
będzie null
.
To tak, jakbyś próbował uzyskać dostęp do obiektu, który jest null
. Rozważ poniższy przykład:
TypeA objA;
W tym momencie właśnie zadeklarowałeś ten obiekt, ale nie został on zainicjowany ani utworzony . I za każdym razem, gdy spróbujesz uzyskać dostęp do dowolnej właściwości lub metody w nim, zostanie rzucona, NullPointerException
co ma sens.
Zobacz również poniższy przykład:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Wyjątek wskaźnika o wartości null jest generowany, gdy aplikacja próbuje użyć wartości null w przypadku, gdy obiekt jest wymagany. Obejmują one:
- Wywołanie metody instancji
null
obiektu. - Dostęp lub modyfikacja pola
null
obiektu. - Biorąc długość
null
tak, jakby to była tablica. - Uzyskiwanie dostępu do gniazd lub modyfikowanie ich
null
tak, jakby to była tablica. - Rzucanie,
null
jakby to była wartość rzucana.
Aplikacje powinny zgłaszać wystąpienia tej klasy, aby wskazać inne nielegalne zastosowania null
obiektu.
Odniesienie: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
null
Wskaźnik jest, że punkty do nikąd. Podczas nieprawidłowego wskaźnika p
, można powiedzieć „daj mi dane w miejscu przechowywane w«p». Kiedy p
to null
wskaźnik, lokalizacja przechowywane w p
to nowhere
, mówisz:«Daj mi dane w miejscu «znikąd»». Oczywiście nie może tego zrobić, więc rzuca null pointer exception
.
Ogólnie rzecz biorąc, dzieje się tak, ponieważ coś nie zostało poprawnie zainicjowane.
Istnieje już wiele wyjaśnień, które wyjaśniają, jak to się dzieje i jak to naprawić, ale należy również postępować zgodnie z najlepszymi praktykami, aby NullPointerExceptionw ogóle ich unikać .
Zobacz też: Lista dobrych praktyk
Dodałbym, bardzo ważne, dobrze wykorzystać final
modyfikator. Używanie modyfikatora „final”, gdy ma to zastosowanie w Javie
Podsumowanie:
- Użyj
final
modyfikatora, aby wymusić dobrą inicjalizację. - Unikaj zwracania wartości null w metodach, na przykład zwracania pustych kolekcji, gdy ma to zastosowanie.
- Użyj adnotacji @NotNulli@Nullable
- Szybka awaria i użyj potwierdzeń, aby uniknąć propagacji obiektów o wartości null w całej aplikacji, gdy nie powinny być puste.
- Najpierw użyj równości ze znanym obiektem:
if("knownObject".equals(unknownObject)
- Wolę
valueOf()
ponadtoString()
. - Użyj zerowych bezpiecznych StringUtilsmetod
StringUtils.isEmpty(null)
. - Użyj Java 8 Optional jako wartości zwracanej w metodach. Klasa Optional zapewnia rozwiązanie do reprezentowania wartości opcjonalnych zamiast odwołań o wartości null.
W Javie wszystko (z wyjątkiem typów pierwotnych) ma postać klasy.
Jeśli chcesz użyć dowolnego obiektu, masz dwie fazy:
- Ogłosić
- Inicjalizacja
Przykład:
- Deklaracja:
Object object;
- Inicjalizacja:
object = new Object();
To samo dotyczy koncepcji tablicy:
- Deklaracja:
Item item[] = new Item[5];
- Inicjalizacja:
item[0] = new Item();
Jeśli nie podajesz sekcji inicjalizacyjnej, plik NullPointerException
Arise.
Wyjątek wskaźnika zerowego jest wskaźnikiem, że używasz obiektu bez inicjalizacji go.
Na przykład poniżej jest klasa studencka, która wykorzysta ją w naszym kodzie.
public class Student {
private int id;
public int getId() {
return this.id;
}
public setId(int newId) {
this.id = newId;
}
}
Poniższy kod zawiera wyjątek wskaźnika zerowego.
public class School {
Student student;
public School() {
try {
student.getId();
}
catch(Exception e) {
System.out.println("Null pointer exception");
}
}
}
Ponieważ używasz student
, ale zapomniałeś zainicjować go tak, jak w poprawnym kodzie pokazanym poniżej:
public class School {
Student student;
public School() {
try {
student = new Student();
student.setId(12);
student.getId();
}
catch(Exception e) {
System.out.println("Null pointer exception");
}
}
}
W Javie wszystkie deklarowane zmienne są w rzeczywistości „odniesieniami” do obiektów (lub prymitywów), a nie samych obiektów.
Podczas próby wykonania jednej metody obiektowej odwołanie prosi żywy obiekt o wykonanie tej metody. Ale jeśli referencja odwołuje się do NULL (nic, zero, void, nada), to nie ma sposobu, aby metoda została wykonana. Następnie środowisko wykonawcze poinformuje Cię o tym, zgłaszając wyjątek NullPointerException.
Twoje odniesienie „wskazuje” na null, stąd „Null -> Pointer”.
Obiekt znajduje się w przestrzeni pamięci maszyny wirtualnej i jedynym sposobem uzyskania do niego dostępu jest użycie this
odwołań. Weź ten przykład:
public class Some {
private int id;
public int getId(){
return this.id;
}
public setId( int newId ) {
this.id = newId;
}
}
I w innym miejscu w Twoim kodzie:
Some reference = new Some(); // Point to a new object of type Some()
Some otherReference = null; // Initiallly this points to NULL
reference.setId( 1 ); // Execute setId method, now private var id is 1
System.out.println( reference.getId() ); // Prints 1 to the console
otherReference = reference // Now they both point to the only object.
reference = null; // "reference" now point to null.
// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );
// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...
Jest to ważna rzecz, o której należy wiedzieć - kiedy nie ma już odniesień do obiektu (w powyższym przykładzie, gdy reference
i otherReference
oba wskazują na wartość null), wówczas obiekt jest „nieosiągalny”. Nie ma sposobu, abyśmy mogli z nim pracować, więc ten obiekt jest gotowy do wyrzucenia elementów bezużytecznych, aw pewnym momencie maszyna wirtualna zwolni pamięć używaną przez ten obiekt i przydzieli inny.
Kolejne wystąpienie a NullPointerException
ma miejsce, gdy deklarujemy tablicę obiektów, a następnie natychmiast próbuje się wyłuskać elementy wewnątrz niej.
String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
Tej konkretnej NPE można uniknąć, jeśli kolejność porównania zostanie odwrócona; mianowicie, użyj .equals
na gwarantowanym obiekcie niezerowym.
Wszystkie elementy wewnątrz tablicy są inicjalizowane do ich wspólnej wartości początkowej ; dla dowolnego typu tablicy obiektów oznacza to, że wszystkie elementy są null
.
Państwo musi zainicjować elementów tablicy przed dostępem lub ich dereferencji.
String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}