Regex em Java: Validando dados com expressões regulares

Alura

No meu sistema de cadastro de alunos eu recebo um aluno com os seguintes atributos:


public class Aluno {
private String nome;
private String sobrenome;
private String telefone;
//métodos
}

Ao imprimir os dados de um aluno:

 Nome: Alex2016 Sobrenome: 12Felipe Telefone: 11992232121455

Alex2016? 12Felipe? E esse telefone bizarro? Esse aluno contém informações que não fazem sentido...

Banner promocional da Imersão Cloud DevOps da Alura e Google Cloud com o texto "INSCRIÇÕES ABERTAS PARA A PRIMEIRA EDIÇÃO DA IMERSÃO CLOUD DEVOPS" e a informação de 3 aulas gratuitas com certificado. A imagem mostra um desenvolvedor focado usando fones de ouvido em um computador, com uma colega trabalhando ao fundo, e um botão chamativo com a frase "GARANTA A SUA VAGA".

Como posso fazer para impedir que esses tipos de dados sejam inseridos no meu sistema?

Vamos tentar validar esses dados criando um método que valida o aluno:


public boolean valida(Aluno aluno) {
//implementação
}

Vamos começar pelo nome do aluno. Não queremos que tenha números nem no começo e nem no final do nome! Como podemos fazer isso?

Vamos extrair tanto o primeiro caracter quanto o último por meio do método charAt() da classe String:


public boolean valida(Aluno aluno) {
String nome = aluno.getNome(); 
char primeiraLetra = nome.charAt(0);
char ultimaLetra = nome.charAt(nome.length() - 1)
}

Para verificar se um caracter é uma letra, podemos usar o método estático isAlphabetic() da classe <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html">Character</a>:


public boolean valida(Aluno aluno) {
String nome = aluno.getNome();
if (Character.isAlphabetic((nome.charAt(0))) && Character.isAlphabetic((nome.charAt(nome.length() - 1)))) { 
    return true;
    }
return false; }

Implementamos nossa primeira validação! Vamos agora adicionar um sysout dentro de um if para testarmos:


if (valida(aluno)) { 
    System.out.println("aluno " + aluno.getNome() + " é válido");
     } else { 
         System.out.println("aluno " + aluno.getNome() + " é inválido");
}

Vamos testar um nome que começa com um número, no caso "1Alex":

 aluno 1Alex é inválido

Ótimo! Funcionou como o esperado. Mas, e se o número estiver no final? Por exemplo, o que foi apresentado no começo: "Alex2016". Vamos ver o resultado:

 aluno Alex2016 é inválido

Aparentemente tudo está funcionando conforme o esperado! Agora, e se um número estivesse no meio do nome? Por exemplo "A1ex":

 aluno A1ex é válido

Eita! Não pensamos nesse caso! Como podemos fazer com que o nome do aluno não tenha nenhum número? Precisaremos "varrer" toda a nossa String, caracter por caracter e verificar se é válido:


public boolean valida(Aluno aluno) {
String nome = aluno.getNome();
for (int i = 0; i < nome.length(); i++) { 
    if (!Character.isAlphabetic((nome.charAt(i)))) { 
        return false; } }
return true; }

Se testarmos novamente com o nome "A1ex":

 aluno A1ex é inválido

Ótimo! Agora o nome do meu aluno está sendo validado conforme o esperado! E se recebermos um aluno que tenha inserido o nome com apenas uma letra? Como "A" por exemplo... o que aconteceria?

 aluno A é válido

Hmmm, mas com certeza para o meu sistema não faz sentido um aluno com o nome de apenas 1 letra...então adicionaremos mais uma condição no nosso validador:


public boolean valida(Aluno aluno) {
String nome = aluno.getNome();
if(nome.length() > 2){ return false; }
//restante do código
}

Se testarmos agora:

 aluno A é inválido

A nossa validação por enquanto está funcionando, mas olha o tamanho que ficou o método:


public boolean valida(Aluno aluno) {
String nome = aluno.getNome();
if(nome.length() > 2){ return false; }
for (int i = 0; i > nome.length(); i++) { 
    if (!Character.isAlphabetic((nome.charAt(i)))) { 
        return false; } }
return true; }

À primeira vista conseguimos entender o que está sendo feito? Provavelmente não.

Note também que a cada validação que precisamos fazer são mais ifs que precisamos adicionar. Será que existe outra forma mais simples para validarmos esses dados? A resposta é sim!

Podemos utilizar expressões regulares por meio do método matches() da classe String. Vamos definir nossa expressão regular para validar o nome do aluno:


public boolean valida(Aluno aluno) {
String nome = aluno.getNome();
return nome.matches("[a-z]");
}

Certo, essa expressão regular significa que esperamos apenas 1 única letra do alfabeto. Mas o que queremos é que tenha pelo menos 2, certo? Simples! Basta adicionar chaves ({}) e informar a quantidade de repetições que você deseja:


public boolean valida(Aluno aluno) {
String nome = aluno.getNome();
return nome.matches("[a-z]{2}");
}

Nesse exemplo estamos informando que queremos apenas 2 repetições, ou seja, a quantidade não pode ser maior ou menor e sim igual a 2 letras! Com certeza não é isso que queremos! E agora? Como podemos dizer que queremos pelo menos 2 letras?

Quando utilizamos as chaves podemos passar 2 parâmetros: o primeiro significa a quantidade mínima e o segundo a quantidade máxima. Ou seja, se adicionarmos apenas uma ",":


public boolean valida(Aluno aluno) {
String nome = aluno.getNome();
return nome.matches("[a-z]{2,}");
}

Nesse instante estamos dizendo que esperamos pelo menos 2 letras e a quantidade máxima não tem limite!

Se testarmos o nome "Alex":

 aluno Alex é inválido

O que aconteceu? Não era pra ser válido? A nossa expressão regular diz que espera pelo menos 2 letras, porém letras minúsculas! Agora, como podemos fazer com que a nossa expressão regular espere uma letra maiúscula no começo? Da mesma forma que pra letras minúsculas usamos [a-z] podemos usar [A-Z] para letras maiúsculas:


public boolean valida(Aluno aluno) {
String nome = aluno.getNome();
return nome.matches("[A-Z][a-z]{1,}");
}

Agora a nossa expressão regular está esperando uma String com a primeira letra maiúscula e por isso precisamos apenas garantir que terá pelo menos 1 letra minúscula depois! Se tentarmos rodar novamente:

 aluno Alex é válido

E se tentarmos com aqueles nomes inválidos? Por exemplo: "A1ex", "1Alex" e o "Alex2016"? Vejamos o resultado:

 aluno A1ex é inválido
 aluno 1Alex é inválido
 aluno Alex2016 é inválido

Excelente! Tudo funciona como o esperado e de uma forma mais clara e de fácil manutenção! Se um dia precisarmos modificar nossa validação, basta adaptar a nossa expressão regular para a nova regra de negócio :)

O que achou da expressão regular? Que tal um desafio? Faça a definição de uma expressão regular para validar um telefone que aceite apenas telefones nesses 2 formatos: (11) 1111-1111 ou (11) 11111-1111. Comente o seu resultado!

E aí, curtiu expressões regulares? Que tal aprender mais sobre o assunto? Na Alura, o curso de expressão regulares aborda mais detalhes sobre esse recurso poderoso que facilita, e muito, a vida do programador na hora de realizar diversas validações!

Alex Felipe
Alex Felipe

Alex é instrutor e desenvolvedor e possui experiência em Java, Kotlin, Android. Atualmente cria conteúdo no canal https://www.youtube.com/@AlexFelipeDev.

Veja outros artigos sobre Programação