Ați observat java.lang.NullPointerException (NPE)? 8 Cele mai bune practici pentru a evita runtime NPE în Java
Publicat: 2020-10-07
Evitați excepția Null Pointer în Java și Java Sfaturi și cele mai bune practici pentru a evita NullPointerException în Java.
În calitate de dezvoltator Java, sunt sigur că trebuie să te-ai confruntat cu excepția Null Pointer (NPE) începând cu prima zi. În majoritatea cazurilor, excepția NPE arată o urmă clară a stivei care indică cauza principală a aceleiași, dar în cazul unei aplicații mari la nivel de întreprindere în care aveți sute de clase, devine un coșmar să aflați cauza principală reală.
Ce este Null Pointer Exception (NPE)?
NullPointerException (NPE)
este o excepție care apare atunci când încercați să utilizați o referință care nu indică nicio locație din memorie (null) ca și cum ar face referire la un obiect.
Apelarea unei metode pe o referință null
sau încercarea de a accesa un câmp al unei referințe nule va declanșa un NPE. Aceasta este cauza cea mai frecventă.
Conform JavaDoc, mai jos sunt cauzele majore pentru NPE:
- Aruncarea
null
ca și cum ar fi o valoareThrowable
. - Apelarea metodei de instanță a unui obiect
null
. - Accesarea sau modificarea câmpului unui obiect
null
. - Luând lungimea
null
ca și cum ar fi o matrice. - Accesarea sau modificarea sloturilor de
null
ca și cum ar fi o matrice.
Acum întrebarea reală este Cum să evitați java.lang.NullPointerException în timpul execuției? În acest tutorial vom analiza câteva exemple care creează NPE în timpul execuției și pașii pe care trebuie să îi efectuăm pentru a rezolva acest lucru.
Să creăm NPE la runtime 1st. Aruncă o privire la exemplul de mai jos CrunchifyNullPointerExceptionTips.java
Vom crea NPE 3 moduri diferite
- NPE va fi aruncat dacă încercați să accesați obiectul nul
- NPE va fi aruncat dacă încercați să convertiți șirul nul
- NPE va fi aruncat dacă încercați să accesați obiectul nul în timpul inițializării clasei
Creați clasa CrunchifyNullPointerExceptionTips.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
package crunchify . com . tutorial ; /** * @author Crunchify.com * Have you Noticed java.lang.NullPointerException (NPE)? 8 Best practices to avoid runtime NPE in Java */ public class CrunchifyNullPointerExceptionTips { public static void main ( String [ ] args ) { try { // Example 1: NPE will be thrown if you are trying to access null Object CrunchifyNPE1 ( ) ; } catch ( NullPointerException crunchifyNPE1 ) { System . out . println ( "Exception in CrunchifyNPE1()" ) ; crunchifyNPE1 . printStackTrace ( ) ; } try { // Example 2: NPE will be thrown if you are trying to convert null String CrunchifyNPE2 ( ) ; } catch ( NullPointerException crunchifyNPE2 ) { System . out . println ( "\nException in CrunchifyNPE2()" ) ; // printStackTrace(): Prints this throwable and its backtrace to the standard error stream. // This method prints a stack trace for this Throwable object on the error output stream that is the value of the field System.err. // The first line of output contains the result of the toString() method for this object. // Remaining lines represent data previously recorded by the method fillInStackTrace(). crunchifyNPE2 . printStackTrace ( ) ; } try { // Example 3: NPE will be thrown if you are trying to access null Object during Class Initialization CrunchifyNPETest npe = new CrunchifyNPETest ( ) ; npe . getName ( ) ; // NullPointerException: Thrown when an application attempts to use null in a case where an object is required. These include: // - Calling the instance method of a null object. // - Accessing or modifying the field of a null object. // - Taking the length of null as if it were an array. // - Accessing or modifying the slots of null as if it were an array. // - Throwing null as if it were a Throwable value. } catch ( NullPointerException crunchifyNPE3 ) { System . out . println ( "\n Exception in CrunchifyNPETest()" ) ; crunchifyNPE3 . printStackTrace ( ) ; } } private static void CrunchifyNPE1 ( ) { Object crunchifyObj = null ; // hasCode(): Returns a hash code value for the object. // This method is supported for the benefit of hash tables such as those provided by java.util.HashMap. crunchifyObj . hashCode ( ) ; } private static void CrunchifyNPE2 ( ) { String crunchifyString ; crunchifyString = "https://crunchify.com" ; // The line 40 declares a variable named "crunchifyString", but, it does not contain a primitive value. Instead it contains a pointer (because the type is String // which is a reference type). Since you did not say as yet what to point to Java sets it to null, meaning "I am pointing at nothing". // In line 41, the new keyword is used to instantiate (or create) an object of type String and the pointer variable "crunchifyString" is assigned this // object. You can now reference the object using the dereferencing operator . (a dot). System . out . println ( "\nvalue: " + crunchifyString . toString ( ) + ", length: " + crunchifyString . length ( ) ) ; System . out . println ( "No NPE exception on line 51" ) ; // Now Let's create NPE String crunchifyString2 = null ; System . out . println ( crunchifyString2 . toString ( ) ) ; } } class CrunchifyNPETest { private String crunchifyName ; public void setName ( String name ) { this . crunchifyName = name ; } public void getName ( ) { printName ( crunchifyName ) ; } private void printName ( String s ) { System . out . println ( s + " (" + s . length ( ) + ")" ) ; } } |
Rezultat:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Exception in CrunchifyNPE1 ( ) java . lang . NullPointerException : Cannot invoke "Object.hashCode()" because "crunchifyObj" is null at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . CrunchifyNPE1 ( CrunchifyNullPointerExceptionTips . java : 59 ) at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . main ( CrunchifyNullPointerExceptionTips . java : 14 ) value : https : //crunchify.com, length: 21 No NPE exception on line 51 Exception in CrunchifyNPE2 ( ) Exception in CrunchifyNPETest ( ) java . lang . NullPointerException : Cannot invoke "String.toString()" because "crunchifyString2" is null at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . CrunchifyNPE2 ( CrunchifyNullPointerExceptionTips . java : 75 ) at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . main ( CrunchifyNullPointerExceptionTips . java : 23 ) java . lang . NullPointerException : Cannot invoke "String.length()" because "s" is null at crunchify . com . tutorial . CrunchifyNPETest . printName ( CrunchifyNullPointerExceptionTips . java : 92 ) at crunchify . com . tutorial . CrunchifyNPETest . getName ( CrunchifyNullPointerExceptionTips . java : 88 ) at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . main ( CrunchifyNullPointerExceptionTips . java : 38 ) Process finished with exit code 0 |
Ei bine, există câteva sfaturi și trucuri pe care le-am putea folosi pentru a evita NullPointerException în timpul execuției. Hai să aruncăm o privire.

Sfat 1:
Eclipse / IntelliJ IDE va încerca să arate NPE în spațiul de lucru. Corectați codul numai în timpul dezvoltării.

Sfat 2:
Adăugați crunchifyI
sNullorEmpty
()
înainte de o operație pe obiect. Adăugați acest lucru la CrunchifyNullPointerExceptionTips.java
1 2 3 4 5 6 7 8 |
public static boolean crunchifyIsNullOrEmpty ( String crunchifyStr ) { if ( crunchifyStr == null ) return true ; else if ( crunchifyStr . trim ( ) . equals ( "" ) ) return true ; else return false ; } |
În mai sus, liniile de program java 55 și 56 vor fi înlocuite cu aceasta.
1 2 3 4 5 6 |
String crunchifyString2 = null ; if ( ! crunchifyIsNullOrEmpty ( crunchifyString2 ) ) { System . out . println ( crunchifyString2 . toString ( ) ) ; } else { System . out . println ( "crunchifyString2 is null" ) ; } |
Sfat 3:
Verificați dacă String este null
sau gol după operația trim().
1 2 3 |
public static boolean isNullOrEmptyAfterTrim ( String crunchifyStr ) { return ( crunchifyStr == null | | crunchifyStr . trim ( ) . length ( ) == 0 ) ; } |
Sfat 4:
Utilizați întotdeauna Try Catch block
pentru a preveni procesul de rulare neîntrerupt.
1 2 3 4 5 |
try { CrunchifyNPE1 ( ) ; } catch ( NullPointerException npe ) { System . out . println ( "Exception in CrunchifyNPE1()" + npe ) ; } |
Sfat 5:
Collections.emptyList()
este preferat datorită unei mai bune manipulări a genericelor.
Sfat 6:
Utilizați Java Assertions
O afirmație este o declarație care vă permite să vă testați presupunerile despre codul dvs. De exemplu, dacă scrieți o metodă care returnează numele în sistem, puteți afirma că returnarea otherName dacă String este nulă.
Utilizarea de bază a aserțiilor ar fi:
1 2 3 4 5 6 7 8 |
assert < Expression > ; // or another usage is assert < Expression1 > : < Expression2 > ; // in our program add line below. private void printName ( String s ) { assert ( s ! = null ) : "Name must be not null" ; System . out . println ( s + " (" + s . length ( ) + ")" ) ; } |
Dar există o captură: Assertion nu este disponibil în mediul de producție și nu ar trebui să folosim Assertion cu nicio logică de afaceri.
Sfat 7:
Încercați să utilizați verificări containsKey()
, containsValue()
, contains()
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com . crunchify . tutorial ; import java . util . * ; /** * @author Crunchify.com * */ public class CrunchifyContainsKeyExample { public static void main ( String args [ ] ) { HashMap < Integer , String > crunchifyMap = new HashMap < Integer , String > ( ) ; // populate hash map crunchifyMap . put ( 1 , "Crunchify" ) ; crunchifyMap . put ( 2 , "wordpress" ) ; crunchifyMap . put ( 3 , "java tutorials" ) ; // check existence of key 4 if ( crunchifyMap . containsKey ( 4 ) ) { System . out . println ( "Check if key 2 exists: " + crunchifyMap . get ( 4 ) ) ; } else { System . out . println ( "NPE for value 4 avoided" ) ; } } } |
Sfat 8:
Ca o concluzie, este întotdeauna o practică bună să aveți grijă de NPE în timpul dezvoltării, mai degrabă depanarea în producție în timpul execuției. Există o serie de alte sfaturi și trucuri disponibile folosind Spring Framework Annotation, Factory Pattern
, Null Object Pattern etc. Dar voi scurta acest lucru acum.
Voi publica un nou tutorial probabil peste o săptămână despre acesta. Rămâneți aproape.
Doriți să adăugați ceva la acest tutorial SAU ați găsit o problemă, vă rugăm să sunați și să furnizați comentariile dvs.