Introdução
Neste laboratório, exploraremos como lidar com potenciais valores null ao trabalhar com a classe wrapper Character do Java. Diferente do tipo primitivo char, o objeto Character pode ser null, e não tratar isso pode levar a erros NullPointerException. Aprenderemos como verificar se um objeto Character é nulo, combinar verificações de nulo com outras verificações de propriedades de caracteres e utilizar a classe Optional para um tratamento de nulos mais seguro.
Através de exemplos práticos, você obterá experiência prática na escrita de código Java robusto que gerencia efetivamente objetos Character nulos, prevenindo erros comuns em tempo de execução e melhorando a confiabilidade de suas aplicações.
Verificar Character Wrapper para Nulo
Nesta etapa, exploraremos como lidar com potenciais valores null ao trabalhar com a classe wrapper Character do Java. Enquanto os tipos primitivos char não podem ser null, a classe wrapper Character, sendo um objeto, pode ser. Lidar com valores null é crucial para prevenir erros NullPointerException, que são comuns em Java e podem travar seu programa.
Começaremos criando um programa Java simples que demonstra como um NullPointerException pode ocorrer quando você tenta usar um método em um objeto Character que é null.
Abra o arquivo
HelloJava.javano editor WebIDE, caso ainda não esteja aberto.Substitua todo o conteúdo do arquivo pelo seguinte código:
public class HelloJava { public static void main(String[] args) { Character myChar = null; // Esta linha causará um NullPointerException se myChar for null // System.out.println("Is myChar a letter? " + Character.isLetter(myChar)); } }Neste código:
- Declaramos uma variável
CharacterchamadamyChare a definimos explicitamente comonull. - A linha comentada
System.out.println("Is myChar a letter? " + Character.isLetter(myChar));tenta chamar o método estáticoCharacter.isLetter()com um argumentonull. EmboraCharacter.isLetter()seja um método estático, passar um objetoCharacternullpara ele ainda resultará em umNullPointerExceptionporque o método internamente tenta fazer o unboxing do objetoCharacterpara seu valor primitivochar, o que não é possível paranull.
- Declaramos uma variável
Salve o arquivo (Ctrl+S ou Cmd+S).
Agora, vamos compilar o programa. Abra o Terminal na parte inferior do WebIDE e execute:
javac HelloJava.javaVocê não deverá ver nenhuma saída se a compilação for bem-sucedida.
Agora, vamos tentar executar o programa. No Terminal, execute:
java HelloJavaComo a linha que causaria o erro está comentada, o programa será executado sem nenhuma saída ou erros. Isso demonstra que simplesmente declarar um
Charactercomonullnão causa um problema imediato; o problema surge quando você tenta realizar operações nele.
Na próxima etapa, removeremos o comentário da linha problemática e observaremos o NullPointerException.
Combinar Verificações de Nulo e Letra
Na etapa anterior, vimos como um NullPointerException pode ocorrer ao trabalhar com objetos Character. Agora, vamos remover o comentário da linha que causa o erro e ver a exceção em ação. Em seguida, aprenderemos uma maneira comum de evitar isso, combinando uma verificação de nulo com a verificação de letra.
Abra o arquivo
HelloJava.javano editor WebIDE.Remova o comentário da linha que chama
Character.isLetter(). Seu código agora deve ser semelhante a este:public class HelloJava { public static void main(String[] args) { Character myChar = null; // Esta linha causará um NullPointerException se myChar for null System.out.println("Is myChar a letter? " + Character.isLetter(myChar)); } }Salve o arquivo (Ctrl+S ou Cmd+S).
Compile o programa modificado no Terminal:
javac HelloJava.javaNovamente, você não deverá ver nenhuma saída se a compilação for bem-sucedida.
Agora, execute o programa:
java HelloJavaVocê deverá ver uma saída semelhante a esta, indicando um
NullPointerException:Exception in thread "main" java.lang.NullPointerException at java.base/java.lang.Character.isLetter(Character.java:xxxx) at HelloJava.main(HelloJava.java:x)Este erro ocorre porque
myCharénull, e o métodoCharacter.isLetter()não pode operar em um objetonull.Para evitar este
NullPointerException, podemos adicionar uma verificação para ver semyCharénullantes de tentarmos chamarCharacter.isLetter(). Podemos usar uma instruçãoifpara isso. Modifique seu arquivoHelloJava.javapara incluir esta verificação:public class HelloJava { public static void main(String[] args) { Character myChar = null; if (myChar != null && Character.isLetter(myChar)) { System.out.println("myChar is a letter."); } else { System.out.println("myChar is not a letter or is null."); } } }Neste código atualizado:
- Usamos uma instrução
ifcom duas condições combinadas por&&(o operador lógico AND). - A primeira condição,
myChar != null, verifica semyCharnão é nulo. - A segunda condição,
Character.isLetter(myChar), verifica semyCharé uma letra. - O operador
&&é "short-circuiting" (curto-circuito). Isso significa que se a primeira condição (myChar != null) for falsa, a segunda condição (Character.isLetter(myChar)) não é avaliada. Isso evita oNullPointerExceptionporque só tentamos chamarCharacter.isLetter()semyCharnão for nulo.
- Usamos uma instrução
Salve o arquivo.
Compile o programa novamente:
javac HelloJava.javaExecute o programa:
java HelloJavaDesta vez, o programa deve ser executado sem erros e imprimir:
myChar is not a letter or is null.Isso ocorre porque
myCharénull, então a primeira condição na instruçãoif(myChar != null) é falsa, e o blocoelseé executado.
Esta abordagem de verificar se há null antes de acessar os métodos ou propriedades de um objeto é uma técnica fundamental em Java para evitar NullPointerExceptions.
Usar Optional para Segurança contra Nulos
Na etapa anterior, aprendemos como prevenir NullPointerExceptions verificando explicitamente se um objeto é null antes de usá-lo. Embora eficaz, isso pode, às vezes, levar a um código que é preenchido com verificações de nulo. O Java 8 introduziu a classe Optional como uma forma de lidar com valores potencialmente nulos de uma maneira mais funcional e expressiva.
Optional é um objeto container que pode ou não conter um valor não nulo. Se um valor estiver presente, isPresent() retorna true e get() retorna o valor. Se nenhum valor estiver presente, o objeto é considerado vazio e isPresent() retorna false. Chamar get() em um Optional vazio lança um NoSuchElementException.
Vamos refatorar nosso exemplo para usar Optional<Character> para lidar com a possibilidade de um Character nulo.
Abra o arquivo
HelloJava.javano editor WebIDE.Substitua todo o conteúdo do arquivo pelo seguinte código:
import java.util.Optional; public class HelloJava { public static void main(String[] args) { Character myChar = null; // Ainda potencialmente nulo // Crie um Optional a partir do Character potencialmente nulo Optional<Character> optionalChar = Optional.ofNullable(myChar); // Use os métodos Optional para verificar e processar o valor if (optionalChar.isPresent() && Character.isLetter(optionalChar.get())) { System.out.println("myChar is a letter."); } else { System.out.println("myChar is not a letter or is null."); } // Outra forma usando os métodos funcionais do Optional (mais avançado) // optionalChar.filter(Character::isLetter) // .ifPresentOrElse( // c -> System.out.println("myChar is a letter (using Optional methods)."), // () -> System.out.println("myChar is not a letter or is null (using Optional methods).") // ); } }Neste código:
- Importamos a classe
Optional. - Ainda declaramos
myCharcomo potencialmentenull. Optional<Character> optionalChar = Optional.ofNullable(myChar);cria um objetoOptional.Optional.ofNullable()é usado quando o valor pode ser nulo. SemyCharfor nulo,optionalCharserá umOptionalvazio. SemyChartiver um valor,optionalCharconterá esse valor.- Em seguida, usamos
optionalChar.isPresent()para verificar se oOptionalcontém um valor antes de tentar obtê-lo comoptionalChar.get()e passá-lo paraCharacter.isLetter(). Isso é semelhante à nossa verificação de nulo anterior, mas usa a APIOptional. - A seção comentada mostra uma maneira mais avançada de usar
Optionalcom métodos funcionais comofiltereifPresentOrElse, o que pode tornar o código mais conciso para certos cenários. Não focaremos neste uso avançado neste laboratório introdutório, mas é bom estar ciente disso.
- Importamos a classe
Salve o arquivo.
Compile o programa:
javac HelloJava.javaExecute o programa:
java HelloJavaA saída deve ser a mesma da etapa anterior:
myChar is not a letter or is null.Isso confirma que o uso de
Optional.ofNullable()eisPresent()lida corretamente com o caso nulo.
Agora, vamos mudar myChar para um caractere não nulo para ver como o programa se comporta.
Modifique o arquivo
HelloJava.javapara definirmyCharcomo um caractere, por exemplo, 'A':import java.util.Optional; public class HelloJava { public static void main(String[] args) { Character myChar = 'A'; // Agora myChar tem um valor // Crie um Optional a partir do Character potencialmente nulo Optional<Character> optionalChar = Optional.ofNullable(myChar); // Use os métodos Optional para verificar e processar o valor if (optionalChar.isPresent() && Character.isLetter(optionalChar.get())) { System.out.println("myChar is a letter."); } else { System.out.println("myChar is not a letter or is null."); } } }Salve o arquivo.
Compile o programa:
javac HelloJava.javaExecute o programa:
java HelloJavaDesta vez, a saída deve ser:
myChar is a letter.Isso mostra que, quando
myChartem um valor,optionalChar.isPresent()retornatrue, e a verificaçãoCharacter.isLetter()é executada corretamente.
Usar Optional pode tornar seu código mais legível e indicar explicitamente quando um valor pode estar ausente, reduzindo a probabilidade de NullPointerExceptions inesperados.
Resumo
Neste laboratório, aprendemos como lidar com valores potencialmente null ao trabalhar com a classe wrapper Character em Java. Começamos demonstrando como um NullPointerException pode ocorrer ao tentar usar um método em um objeto Character null, mesmo com métodos estáticos como Character.isLetter(). Isso destacou a importância de verificar explicitamente se há null antes de realizar operações em objetos Character para evitar falhas no programa.



