Java NullPointerException – Erkennen, beheben und bewährte Verfahren

java.lang.NullPointerException ist eine der beliebtesten Ausnahmen in der Java Programmierung. Jeder, der in Java arbeitet, hat gesehen, wie dies aus dem Nichts in dem Java Standalone-Programm sowie der Java-Webanwendung auftaucht.

java.lang.NullPointerException

NullPointerException ist eine Laufzeitausnahme, daher müssen wir sie im Programm nicht abfangen. Eine NullPointerException wird in einer Anwendung ausgelöst, wenn wir versuchen, eine Operation auf null durchzuführen, wo ein Objekt benötigt wird. Einige der häufigsten Gründe für NullPointerException in Java-Programmen sind:

  1. Aufrufen einer Methode auf einer Objektinstanz, aber zur Laufzeit ist das Objekt null.
  2. Zugriff auf Variablen einer Objektinstanz, die zur Laufzeit null ist.
  3. Werfen von null im Programm
  4. Zugriff auf Index oder Änderung des Wertes eines Index eines Arrays, das null ist
  5. Überprüfen der Länge eines Arrays, das zur Laufzeit null ist.

Beispiele für Java NullPointerException

Lassen Sie uns einige Beispiele für NullPointerException in Java-Programmen betrachten.

1. NullPointerException beim Aufrufen einer Instanzmethode

public class Temp {

	public static void main(String[] args) {

		Temp t = initT();
		
		t.foo("Hi");
		
	}

	private static Temp initT() {
		return null;
	}

	public void foo(String s) {
		System.out.println(s.toLowerCase());
	}
}

Wenn wir das obige Programm ausführen, wird folgende NullPointerException-Fehlermeldung ausgegeben.

Exception in thread "main" java.lang.NullPointerException
	at Temp.main(Temp.java:7)

Wir erhalten eine NullPointerException in der Anweisung t.foo("Hi");, weil „t“ hier null ist.

2. Java NullPointerException beim Zugriff/Ändern eines Feldes eines null-Objekts

public class Temp {

	public int x = 10;
	
	public static void main(String[] args) {

		Temp t = initT();
		
		int i = t.x;
		
	}

	private static Temp initT() {
		return null;
	}

}

Das obige Programm wirft folgenden NullPointerException-Stack-Trace aus.

Exception in thread "main" java.lang.NullPointerException
	at Temp.main(Temp.java:9)

NullPointerException wird in der Anweisung int i = t.x; geworfen, weil „t“ hier null ist.

3. Java NullPointerException, wenn null als Methodenargument übergeben wird

public class Temp {

	public static void main(String[] args) {

		foo(null);

	}

	public static void foo(String s) {
		System.out.println(s.toLowerCase());
	}
}

Dies ist eines der häufigsten Vorkommnisse von java.lang.NullPointerException, weil der Aufrufer das Null-Argument übergibt.

Das folgende Bild zeigt die Nullzeigerausnahme, wenn das obige Programm in der Eclipse IDE ausgeführt wird.

4. java.lang.NullPointerException, wenn null geworfen wird

public class Temp {

	public static void main(String[] args) {

		throw null;
	}

}

Nachfolgend finden Sie der Ausnahmestapelablauf des obigen Programms, der eine NullPointerException aufgrund der Anweisung throw null; anzeigt.

Exception in thread "main" java.lang.NullPointerException
	at Temp.main(Temp.java:5)

5. NullPointerException beim Abrufen der Länge eines Null-Arrays

public class Temp {

	public static void main(String[] args) {

		int[] data = null;
		
		int len = data.length;
	}

}
Exception in thread "main" java.lang.NullPointerException
	at Temp.main(Temp.java:7)

6. NullPointerException beim Zugriff auf den Indexwert eines Null-Arrays

public class Temp {

	public static void main(String[] args) {

		int[] data = null;
		
		int len = data[2];
	}

}
Exception in thread "main" java.lang.NullPointerException
	at Temp.main(Temp.java:7)

7. NullPointerException beim Synchronisieren auf einem Null-Objekt

public class Temp {

	public static String mutex = null;
	
	public static void main(String[] args) {

		synchronized(mutex) {
			System.out.println("synchronized block");
		}		
	}
}

Das synchronized(mutex) wirft eine NullPointerException, weil das Objekt „mutex“ null ist.

8. HTTP-Status 500 java.lang.NullPointerException

Manchmal erhalten wir eine Fehlerseitenantwort von einer Java-Webanwendung mit einer Fehlermeldung wie „HTTP-Status 500 – Interner Serverfehler“ und der Ursache als java.lang.NullPointerException.

Dafür habe ich das Spring MVC Beispiel Projekt bearbeitet und die HomeController-Methode wie folgt geändert.

@RequestMapping(value = "/user", method = RequestMethod.POST)
	public String user(@Validated User user, Model model) {
		System.out.println("User Page Requested");
		System.out.println("User Name: "+user.getUserName().toLowerCase());
		System.out.println("User ID: "+user.getUserId().toLowerCase());
		model.addAttribute("userName", user.getUserName());
		return "user";
	}

Das folgende Bild zeigt die Fehlermeldung, die von der Webanwendungsantwort ausgelöst wurde.

Hier ist der Ausnahmestapel:

HTTP Status 500Internal Server Error

Type Exception Report

Message Request processing failed; nested exception is java.lang.NullPointerException

Description The server encountered an unexpected condition that prevented it from fulfilling the request.

Exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Root Cause

java.lang.NullPointerException
	com.journaldev.spring.controller.HomeController.user(HomeController.java:38)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:498)

Die Ursache ist eine NullPointerException in der Anweisung user.getUserId().toLowerCase(), weil user.getUserId() null zurückgibt.

Wie erkennt man java.lang.NullPointerException

Die Erkennung von NullPointerException ist sehr einfach, schauen Sie einfach auf die Ausnahmespur, und sie zeigt Ihnen den Klassennamen und die Zeilennummer der Ausnahme. Schauen Sie dann den Code an und sehen Sie, was möglicherweise null ist und die NullPointerException verursacht. Schauen Sie sich einfach alle oben genannten Beispiele an, aus dem Stapelverfolgungsprotokoll ist sehr klar, was die Nullzeiger Ausnahme verursacht.

Wie behebt man NullPointerException

java.lang.NullPointerException ist eine unbeaufsichtigte Ausnahme, daher müssen wir sie nicht abfangen. Die Nullzeiger-Ausnahmen können durch Null-Überprüfungen und vorbeugende Kodierungstechniken verhindert werden. Schauen Sie sich untenstehende Codebeispiele an, die zeigen, wie man java.lang.NullPointerException vermeiden kann.

if(mutex ==null) mutex =""; // Vorbeugende Kodierung
		
synchronized(mutex) {
	System.out.println("synchronized block");
}
// Verwendung von Null-Überprüfungen
if(user!=null && user.getUserName() !=null) {
System.out.println("User Name: "+user.getUserName().toLowerCase());
}
if(user!=null && user.getUserName() !=null) {
	System.out.println("User ID: "+user.getUserId().toLowerCase());
}

Codierungsbest Practices zur Vermeidung von NullPointerException

1. Betrachten wir die untenstehende Funktion und achten auf Szenarien, die eine Null-Zeiger-Ausnahme verursachen können.

public void foo(String s) {
    if(s.equals("Test")) {
	System.out.println("test");
    }
}

Die NullPointerException kann auftreten, wenn das Argument als null übergeben wird. Die gleiche Methode kann wie folgt geschrieben werden, um eine NullPointerException zu vermeiden.

public void foo(String s) {
	if ("Test".equals(s)) {
		System.out.println("test");
	}
}

2. Wir können auch eine Nullüberprüfung für das Argument hinzufügen und bei Bedarf IllegalArgumentException werfen.

public int getArrayLength(Object[] array) {
	
	if(array == null) throw new IllegalArgumentException("array is null");
	
	return array.length;
}

3. Wir können den ternären Operator verwenden, wie im folgenden Beispielcode gezeigt.

String msg = (str == null) ? "" : str.substring(0, str.length()-1);

4. Verwenden Sie String.valueOf() anstelle der toString() Methode. Zum Beispiel ist der Code für die Methode PrintStream println() wie folgt definiert.

public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }

Das folgende Code-Snippet zeigt das Beispiel, in dem die valueOf() Methode anstelle von toString() verwendet wird.

Object mutex = null;

// gibt null aus
System.out.println(String.valueOf(mutex));

// wirft java.lang.NullPointerException
System.out.println(mutex.toString());

5. Schreiben Sie Methoden, die leere Objekte zurückgeben, anstatt null, wo immer möglich, zum Beispiel leere Liste, leerer String, etc.

6. In den Sammlungsklassen sind einige Methoden definiert, um NullPointerException zu vermeiden. Sie sollten sie verwenden. Zum Beispiel contains(), containsKey() und containsValue().

Referenz: API-Dokument

Source:
https://www.digitalocean.com/community/tutorials/java-lang-nullpointerexception