Exceção de ponteiro nulo em Java
Uma NullPointerException em Java é uma RuntimeException. Ocorre quando um programa tenta usar uma referência de objeto que possui o valor nulo. Em Java, 'nulo' é um valor especial que pode ser atribuído a referências de objetos para indicar a ausência de um valor.
Razões para exceção de ponteiro nulo
Uma NullPointerException ocorre pelos seguintes motivos:
- Invocando um método a partir de um objeto nulo.
- Acessando ou modificando o campo de um objeto nulo.
- Tomando o comprimento de null como se fosse um array.
- Acessando ou modificando os slots de objetos nulos como se fosse um array.
- Jogando null como se fosse um valor Throwable.
- Quando você tenta sincronizar em um objeto nulo.
Exemplo:
Java public class Geeks { public static void main ( String [] args ) { // Reference set to null String s = null ; System . out . println ( s . length ()); } }
Saída:
Hangup (SIGHUP)
Exception in thread 'main' java.lang.NullPointerException
at Geeks.main(Geeks.java:10)Explicação: Neste exemplo, a referência da string 's' é nula. Quando o programa tenta chamar o método length() ele lança uma NullPointerException porque não há nenhum objeto real.
Por que null é usado em Java?
O valor nulo serve como espaço reservado e indica que nenhum valor foi atribuído a uma variável de referência. As aplicações comuns incluem:
- Estruturas de dados vinculadas : representa o final de uma lista ou galho de árvore.
- Padrões de projeto : Isso é usado em padrões como Null Object Pattern ou Singleton Pattern.
Como evitar NullPointerException
Para evitar o NullPointerException devemos garantir que todos os objetos sejam inicializados corretamente antes de usá-los. Quando declaramos uma variável de referência, devemos verificar se o objeto não é nulo antes de solicitarmos um método ou campo dos objetos.
1. Usando literais de string em equals()
Um problema de caso muito comum envolve a comparação entre uma variável String e um literal. O literal pode ser uma String ou um elemento de um Enum. Em vez de invocar o método a partir do objeto nulo, considere invocá-lo a partir do literal.
Exemplo:
Java import java.io.* ; class Geeks { public static void main ( String [] args ) { // Initializing String variable with null value String s = null ; // Checking if s.equals null try { // This line of code throws NullPointerException because s is null if ( s . equals ( 'gfg' )) System . out . print ( 'Same' ); else System . out . print ( 'Not Same' ); } catch ( NullPointerException e ) { System . out . print ( 'NullPointerException Caught' ); } } }
Saída
NullPointerException Caught
Podemos evitar NullPointerException chamando equals em literal em vez de objeto.
Java import java.io.* ; class Geeks { public static void main ( String [] args ) { // Initializing String variable with null value String s = null ; // Checking if s is null using try catch try { if ( 'gfg' . equals ( s )) System . out . print ( 'Same' ); else System . out . print ( 'Not Same' ); } catch ( NullPointerException e ) { System . out . print ( 'Caught NullPointerException' ); } } }
Saída
Not Same
Observação : sempre invoque iguais no literal para evitar chamar um método em uma referência nula.
2. Verificando argumentos do método
Antes de executar o corpo do novo método, devemos primeiro verificar seus argumentos em busca de valores nulos e continuar com a execução do método somente quando os argumentos forem verificados corretamente. Caso contrário, lançará uma IllegalArgumentException e notificará o método de chamada de que algo está errado com os argumentos passados.
Exemplo:
Java import java.io.* ; class Geeks { public static void main ( String [] args ) { // String s set an empty string and calling getLength() String s = '' ; try { System . out . println ( getLength ( s )); } catch ( IllegalArgumentException e ) { System . out . println ( 'IllegalArgumentException caught' ); } // String s set to a value and calling getLength() s = 'GeeksforGeeks' ; try { System . out . println ( getLength ( s )); } catch ( IllegalArgumentException e ) { System . out . println ( 'IllegalArgumentException caught' ); } // Setting s as null and calling getLength() s = null ; try { System . out . println ( getLength ( s )); } catch ( IllegalArgumentException e ) { System . out . println ( 'IllegalArgumentException caught' ); } } public static int getLength ( String s ) { if ( s == null ) throw new IllegalArgumentException ( 'The argument cannot be null' ); return s . length (); } }
Saída
0 13 IllegalArgumentException caught
3. Use o operador ternário
O operador ternário pode ser usado para evitar NullPointerException. Primeiro, a expressão booleana é avaliada. Se a expressão for verdadeira, o valor1 será retornado, caso contrário, o valor2 será retornado. Podemos usar o operador ternário para lidar com ponteiros nulos.
Exemplo:
Java import java.io.* ; class Geeks { public static void main ( String [] args ) { String s = null ; String m = ( s == null ) ? '' : s . substring ( 0 5 ); System . out . println ( m ); s = 'Geeksforgeeks' ; m = ( s == null ) ? '' : s . substring ( 0 5 ); System . out . println ( m ); } }
Saída
Geeks
Explicação : o operador ternário ajuda a verificar nulos e evitar operações em referências nulas.
4. Usando classe opcional (Java 8+)
Em Java 8, a classe Opcional foi introduzida como um objeto contêiner que pode ou não conter um valor não nulo. Ajuda a evitar NullPointerException forçando o tratamento explícito do caso quando um valor está ausente.
Exemplo:
Java import java.util.Optional ; public class OptionalExample { public static void main ( String [] args ) { Optional < String > name = Optional . ofNullable ( null ); // Safe way to access System . out . println ( name . orElse ( 'Default Name' )); // prints: Default Name } }
Saída
Default Name
Explicação: Opcional.ofNullable(value) envolve o valor que pode ser nulo. orElse() fornece um substituto se o valor não estiver presente.