Java - ce este nullpointerexception și cum se rezolvă, cod q - un rus (en)

Când declarați o variabilă de referință (adică un obiect), creați un indicator pentru obiect. Luați în considerare următorul cod în care declarați o variabilă de tip int primitiv.







În acest exemplu, variabila x este int și Java o inițializează pentru 0. Când îi alocați 10 pe a doua linie, valoarea dvs. de 10 este scrisă în locația de memorie indicată de x.

Dar, când încercați să declarați un tip de referință, se întâmplă altceva. Luați următorul cod:

Prima linie declară o variabilă numită num. dar nu conține o valoare primitivă. În schimb, conține un pointer (deoarece tipul Integer este un tip de referință). Din moment ce nu ați spus încă ce să indicați Java, acesta stabilește valoarea la nul, ceea ce înseamnă că "eu nu specific nimic".

În al doilea rând, noul cuvânt cheie este folosit pentru a crea (sau a crea) un obiect de tip Integer, iar pointerul variabil num este atribuit acestui obiect. Acum vă puteți referi la obiect folosind operatorul de dereferencing. (Dot).

Excepția pe care ați cerut-o se ridică atunci când declarați o variabilă, dar nu creați un obiect. Dacă încercați să dereference num crearea unui obiect, veți obține un NullPointerException. În cele mai banale cazuri, compilatorul va prinde problema și vă va spune că "num nu poate fi inițializat", dar uneori scrieți un cod care nu creează direct obiectul.

De exemplu, este posibil să aveți următoarea metodă:

În acest caz, nu creați un obiect obj. mai degrabă presupunând că a fost creat înainte de metoda doSomething doSomething. Din păcate, această metodă poate fi apelată după cum urmează:

În acest caz, obj este nul. Dacă metoda este destinată să facă ceva cu obiectul trecut, este recomandabil să aruncați NullPointerException deoarece este o eroare de programator și programatorul va avea nevoie de această informație pentru depanare.

Alternativ, pot exista cazuri în care scopul metodei nu este numai de a lucra cu obiectul transferat și, prin urmare, parametrul nul poate fi acceptabil. În acest caz, va trebui să verificați parametrul nul și să vă comportați diferit. De asemenea, trebuie să explicați acest lucru în documentație. De exemplu, doSomething poate fi scrisă ca:

În cele din urmă, modul de determinare a locației excepției și apelarea utilizării Traseului de stivă

Excepția NullPointerException este o excepție care apare atunci când încercați să utilizați o referință care indică faptul că nu există nici o locație în memorie (null), ca în cazul în care se referă la un obiect. Apelarea metodei pe o referință null sau încercarea de a accesa câmpul de referință null va apela NullPointerException. Acestea sunt cele mai frecvente, dar alte metode sunt listate pe pagina de javadoc NullPointerException.

Probabil cel mai rapid exemplu de cod pe care l-am putut găsi pentru a ilustra NullPointerException. va:

Un loc bun pentru a începe este JavaDocs. Acestea acoperă:

Se aruncă atunci când aplicația încearcă să utilizeze nul în cazul în care este necesar un obiect. Acestea includ:

  • Apelarea metodei instanței obiectului zero.
  • Accesați sau modificați câmpul obiectului zero.
  • Luând lungimea nulului, ca și cum ar fi o matrice.
  • Accesați sau schimbați sloturile nul, ca și cum ar fi fost o matrice.
  • Aruncarea unei valori zero, ca și cum ar fi o valoare Throwable.

Aplicațiile trebuie să arunce instanțe din această clasă pentru a indica o altă utilizare ilegală a obiectului nul.

De asemenea, se întâmplă dacă încercați să utilizați o referință null cu sincronizată. acest lucru cauzează de asemenea această excepție pentru JLS.

  • În caz contrar, dacă valoarea Expression este nulă, NullPointerException.

Deci, aveți un NullPointerException. cum o rezolvi? Să luăm un exemplu simplu care solicită NullPointerException

Definiți valorile zero

Aici vedem că excepția a fost selectată în rândul 13 (în metoda printString). Uita-te la linia și verifica ce valori sunt zero prin adăugarea de instrucțiuni de logare sau folosind un debugger. Am constatat că s este nulă, iar apelarea metodei de lungime pe ea aruncă o excepție. Vedem că programul nu mai face o excepție atunci când s.length () este eliminat din metoda.

Urmărirea, în care provin aceste valori

Apoi verificați de unde provine această valoare. În urma apelurilor metodelor, vedem că s este trecut prin printString (nume) în metoda print (). și acest nume este nul.

Urmărirea, unde trebuie stabilite aceste valori

Unde este dat? În setName (String). Cu unele depanări suplimentare, vedem că această metodă nu este apelată deloc. Dacă a fost apelată această metodă, asigurați-vă că ați verificat ordinea de apelare a acestor metode și că metoda setată nu este apelată după metoda de tipărire.

Acest lucru este suficient pentru a ne oferi o soluție: adăugați apelul la printer.setName () înainte de a apela printer.print ().

O variabilă poate avea o valoare implicită (și setName o poate împiedica să fie setată la nul):

Fie metoda de tipărire, fie PrintString pot verifica valoarea nulă. de exemplu:

Sau puteți crea o clasă astfel încât numele să aibă întotdeauna o valoare nonzero.

Dacă ați încercat să depanați o problemă și încă nu aveți o soluție, puteți trimite întrebarea pentru mai mult ajutor, dar nu uitați să includeți ceea ce ați încercat până acum. La cel puțin, includeți stacktrace în întrebare și marcați numerele de linie importante din cod. De asemenea, încercați să simplificați mai întâi codul (consultați SSCCE).

Î: Ce este NullPointerException?

După cum trebuie să știți, tipurile Java sunt împărțite în tipuri primitive (boolean, int, etc.) și tipuri de referințe. Tipurile de referință din Java vă permit să utilizați o valoare specială nulă, care este o metodă Java care spune "fără obiect".







Un NullPointerException la timpul de execuție atunci când programul dvs. încearcă să utilizeze null ca și cum ar fi o referință reală. De exemplu, dacă scrieți acest lucru:

Operatorul etichetat "AICI" va încerca să ruleze metoda length () într-o referință nulă și acest lucru va apela NullPointerException.

Există mai multe moduri de a utiliza o valoare nulă, care va duce la un NullPointerException. Dacă este adevărat, singurul lucru pe care îl puteți face cu nulul fără apariția unui NPE este:

Întrebare: Cum știu stiva NPE?

Să presupunem că compilați și rulați programul de mai sus:

Prima observație: compilația are succes! Problema din program nu este o eroare de compilare. Aceasta este o eroare de execuție. (Unele IDE-uri vă pot avertiza că programul dvs. va arunca întotdeauna o excepție, dar compilatorul standard javac nu face acest lucru.)

A doua observație: când conduc programul, acesta afișează două rânduri de "gobbledy-gook". WRONG !! Acest lucru nu este afectuos. Asta e stacktrace. și furnizează informații importante. care vă va ajuta să urmăriți eroarea în codul dvs. dacă aveți timp să îl citiți cu atenție.

Deci, să vedem ce spune:

Prima linie a stivei de stivă vă spune câteva lucruri:

  • Acesta vă spune numele firului Java în care a fost selectată excepția. Pentru un program simplu cu un fir (ca acesta), acesta va fi "de bază". Să mergem mai departe.
  • Acesta vă spune numele complet al excepției selectate; Ie java.lang.NullPointerException.
  • Dacă în excepție există un mesaj de eroare asociat, acesta va fi afișat după numele excepției. În acest sens, NullPointerException este neobișnuit, deoarece are rareori un mesaj de eroare.

A doua linie este cea mai importantă în diagnosticarea NPE.

Acest lucru ne spune câteva lucruri:

  • "În Test.main" se spune că am fost în metoda principală a clasei de test.
  • "Test.java:4" dă numele fișierului sursă pentru clasă și ne spune că instrucțiunea, unde sa întâmplat, este în linia 4 a fișierului.

Rețineți că, într-un exemplu mai complex, există mai multe rânduri în urma stivei NPE. Dar puteți fi sigur că a doua linie (prima linie de pe linie) vă va spune unde a fost aruncat NPE 1.

Pe scurt, stacktrace ne va spune neechivoc care dintre programele programate de NPE a aruncat.

1 - Nu este corect. Există lucruri numite excepții imbricate.

Întrebare: Cum pot determina motivul excepției NPE din codul meu?

Aceasta este o parte dificilă. Răspunsul scurt este de a aplica o deducere logică a dovezilor furnizate de următoarea stivă, codul sursă și documentația API corespunzătoare.

Să ilustrăm mai întâi un exemplu simplu (a se vedea mai sus). Începem prin examinarea liniei despre care ni sa spus prin stacktrace, unde apare NPE:

Cum poate cauza acest lucru un NPE?

De fapt, există o singură cale: acest lucru se poate întâmpla numai dacă foo este nul. Apoi încercăm să executăm metoda length () pe null și. BANG!

Dar (v-am auzit spunem) că dacă un NPE a fost aruncat într-un apel la metoda length ().

Dacă se întâmplă acest lucru, stiva va arăta diferită. Prima linie "la" va indica faptul că excepția a fost selectată într-o linie din clasa java.lang.String. iar linia 4 a Test.java ar fi a doua linie "la".

Deci, de unde a venit asta? În acest caz, este evident și, evident, ceea ce trebuie să facem pentru a rezolva acest lucru. (Atribuiți o valoare non-zero pentru foo)

Ok, haideți să încercăm un exemplu mai puțin viclean. Acest lucru va necesita o inferență logică.

Deci, acum avem 2 linii "on line". Primul este pentru această linie:

Și al doilea - pentru această linie:

Deci, uita la prima linie, cum poate cauza asta NPE? De fapt, există două moduri:

  • Dacă valoarea barei este nulă, atunci bar [pos] va apela NPE.
  • Dacă bara [pos] este nulă, atunci lungimea () apelați pe ea va apela NPE.

Prin urmare, trebuie să aflăm care dintre aceste scenarii explică ce se întâmplă de fapt. Să începem prin studierea primului:

De unde vine bara? Acesta este parametrul pentru apelarea metodei de testare. și dacă ne uităm la cum a fost numit testul. putem vedea că provine din variabila statică variabilă. Și vedem clar că am inițializat foo la o valoare nonzero. Acest lucru este suficient pentru a respinge în mod condiționat această explicație. (Teoretic, altceva poate schimba foo la nul, dar acest lucru nu se întâmplă aici).

Și cum rămâne cu cel de-al doilea scenariu? Ei bine, vedem că pos este 1. Prin urmare, aceasta înseamnă că foo [1] trebuie să fie nul. Este posibil acest lucru?

Într-adevăr! Și asta e problema. Când inițializăm așa:

Alocăm String [] cu două elemente care sunt inițializate la null. Și apoi nu am schimbat conținutul foo. astfel încât foo [1] va fi în continuare nul.

O excepție de pointer nul apare atunci când căutați o variabilă care indică nul. Vedeți următorul cod:

O excepție a indicatorului nul este aruncată atunci când aplicația încearcă să utilizeze nul în cazul în care este necesar un obiect. Acestea includ:

  1. Apelați metoda instanței nulă a obiectului.
  2. Accesați sau modificați câmpul nul al obiectului.
  3. Luând lungimea null ca și cum ar fi o matrice.
  4. Accesați sau modificați slots null ca și cum ar fi o matrice.
  5. Aruncarea null ca și cum ar fi o valoare Throwable.

Aplicațiile trebuie să arunce instanțe din această clasă pentru a indica o altă utilizare ilegală a obiectului nul.

Indicatorul NULL este cel care indică nicăieri. Când căutați indicatorul p. spuneți "dați-mi datele în locul stocat în" p ". Când p este un pointer nul, locația stocată în p. Nicăieri nu spuneți, spuneți "dați-mi datele în locul" Nicăieri ". Evident, el nu poate face acest lucru, deci el este NULL pointer exception.

În general, acest lucru se datorează faptului că ceva nu a fost inițializat corespunzător.

Multe explicații există deja pentru a explica cum se întâmplă acest lucru și cum să remediați acest lucru, dar trebuie, de asemenea, să urmați recomandările pentru a exclude complet NullPointerException.

  1. Utilizați modificatorul final pentru a asigura o bună inițializare.
  2. Evitați returnarea null în metode, de exemplu, returnarea colecțiilor goale, când este cazul.
  3. Utilizați adnotările @NotNull și @Nullable
  4. Completarea rapidă și utilizarea instrucțiunilor pentru a evita propagarea obiectelor nulă în întreaga aplicație, dacă nu trebuie să fie zero.
  5. Mai întâi, folosiți valorile cu un obiect cunoscut: if ("knownObject" .equals (unknownObject)
  6. Valoarea preferăOf () peste toString ().
  7. Utilizați metode sigure null StringUtils.isEmpty (null).

În Java, toate lucrurile sunt sub forma unei clase.

Dacă doriți să utilizați orice obiect, atunci aveți două faze

Același lucru pentru conceptul Array

  • Declarație: Elementul i [] = element nou [5];
  • Inițializare: i [0] = element nou ();

Dacă nu dați secțiunea NullpointerException, apare NullpointerException.

O excepție cu un pointer nul este un indicator care indică faptul că utilizați obiectul fără a îl inițializa.

De exemplu, mai jos este clasa de studenți care va fi utilizată în codul nostru.

Codul de mai jos vă oferă excepția indicatorului nul.

Din moment ce utilizați Obj_Student, ați uitat să-l inițializați, așa cum se arată în figura de mai jos.

Obiectul trăiește în spațiul de memorie VM, iar accesul la acesta este numai prin intermediul acestor linkuri. Să luăm exemplul următor:

O altă apariție a NullPointerException apare atunci când este declarată o serie de obiecte și apoi încearcă imediat să vadă elementele din interiorul acesteia.

Acest NPE special poate fi evitat dacă ordinul de comparație este anulat; Anume, folosiți ecuațiile pe un obiect garantat nonzero.

Toate elementele din matrice sunt inițializate cu o valoare comună comună; Pentru orice tip de serie de obiecte, aceasta înseamnă că toate elementele sunt nulă.

Trebuie să inițializați elementele din matrice înainte de a le accesa sau de a le debloca.







Trimiteți-le prietenilor: