Verificar se é letra ou número no Java
Estamos desenvolvendo um sistema web para venda de automóveis usados. Uma das informações necessárias para cadastrar um automóvel no sistema é o número da placa do veículo.
Precisamos criar uma funcionalidade que valide as placas do carro, para que os usuários não saiam enviando para o servidor dados incorretos. Uma placa de carro válida por exemplo seria "FXZ-9846" e uma inválida “FX4-Z432”. Para fazer tal validação precisamos seguir algumas regras, sendo elas:
- Número de caracteres tem que ser igual a 7
- Os 3 primeiros caracteres são letras
- Os 4 últimos caracteres são dígitos
Validando a placa
Primeiro, criaremos um método que recebe uma placa e devolve um boolean
para fazer a verificação do que foi inserido.
public static boolean validaPlaca(String placa){
}
Podemos colocar uma variável do tipo boolean
que será nosso retorno após as validações:
public static boolean validaPlaca(String placa){
boolean valido = true;
//aqui ficarão nossas validações
return valido;
}
A primeira validação que vamos fazer será referente ao tamanho da String
. O número de caracteres de uma placa de carro deve ser igual a 7. Colocando essa regra no código:
public static boolean validaPlaca(String placa){
boolean valido = true;
if(placa.length() != 7){
valido = false;
}
return valido;
}
Os três primeiros caracteres tem que ser letras. Para validar isso vamos, primeiramente, usar o método substring() da classe String
. Este método cria uma String
contendo todos os valores desde o primeiro índice passado até o segundo índice menos 1. No nosso caso vamos usar para pegar apenas os três primeiros caracteres da nossa placa. Por enquanto temos isso:
placa.substring(0,3)
Agora precisamos verificar se essa nova String
contém apenas letras, para fazer tal verificação vamos usar o método matches(), também da classe String
, e passar uma expressão regular como parâmetro. Este método devolve um boolean
. Ele verifica se a String
que chamou este método se equipara com o parâmetro passado.
No nosso caso, vamos passar a seguinte expressão regular [A-Z]*
. Essa expressão só permite as letras de A a Z e todas as letras tem que estar em maiúsculo. Portanto, se a String
conter algo diferente do que o permitido pela expressão regular ele retornará false
Vamos usar o método matches()
em conjunto com o substring()
e encapsular dentro de um if
:
if(placa.substring(0, 3).matches("[A-Z]*")){
}
Para finalizar essa validação, vamos negar essa condição, ou seja, só vai entrar no if
caso o matches()
retorne false
, para que possamos alterar o valor de valido
para false
:
if(!placa.substring(0, 3).matches("[A-Z]*")){
valido = false;
}
Por fim, vamos usar exatamente os mesmos métodos, substring()
e matches()
, para validar se os últimos quatro caracteres são dígitos.
A diferença será apenas nos parâmetros passados, para o substring()
vamos passar apenas o valor 3, com isso ele pegará o caractere da String
com índice 3 e como não passamos um valor final ele irá até o final da String
.
Já para o matches()
, vamos passar essa expressão regular: [0-9]*
, ela só permite números de 0 a 9. Assim, temos:
if(!placa.substring(3).matches("[0-9]*")){
return false;
}
Pronto, todas as validações foram feitas, nosso método ficou assim:
public static boolean validaPlaca(String placa){
boolean valido = true;
if(placa.length() != 7){
valido = false;
}
if(!placa.substring(0, 3).matches("[A-Z]*")){
valido = false;
}
if(!placa.substring(3).matches("[0-9]*")){
valido = false;
}
return valido;
}
Para testarmos, usaremos uma placa válida:
public static void main(String[] args) {
System.out.println(validaPlaca("FXZ4765"));
}
Como resultado, temos:
Agora vamos passar uma placa válida com "-", que é a formatação normal de uma placa de carro.
public static void main(String[] args) {
System.out.println(validaPlaca("FXZ-4765"));
}
Reparem no resultado:
A placa é válida, mas recebemos false
, porque? Isso aconteceu pois não prevenimos nosso método contra caracteres especiais ou formatações erradas. Basicamente antes de começar nossas validações devemos tratar a placa recebida para que ela só contenha letras e números.
Para isso vamos usar o método replaceAll() da classe String
, que, por sua vez, substitui todos os caracteres passados no primeiro parâmetro pelos caracteres passados no segundo parâmetro.
No nosso caso vamos usar outra expressão regular, essa: [^a-zA-Z0-9]
. Com ela no primeiro parâmetro do replaceAll()
estamos dizendo que tudo que não for letra de A a Z, seja maiuscula ou minuscula e não for número deve ser substituído. Mas substituído pelo que? Bom, por nada, só queremos tirar esses caracteres da nossa String
. Usando esse método nosso código fica assim:
public static boolean validaPlaca(String placa){
boolean valido = true;
placa = placa.replaceAll("[^a-zA-Z0-9]", "");
if(placa.length() != 7){
valido = false;
}
if(!placa.substring(0, 3).matches("[A-Z]*")){
valido = false;
}
if(!placa.substring(3).matches("[0-9]*")){
valido = false;
}
return valido;
}
Vamos testar novamente usando a mesma placa, FXZ-4765:
Pronto, agora funcionou do jeito que queriamos.
Early Return
Só mais um detalhe, olhando nosso método perceba que não importa como venha a placa, passamos por todos os ifs
, isso não é muito legal. Por exemplo, se o tamanho da placa for diferente de 7 eu quero que o método acabe aí e retorne false
, não tem motivo para passar pelas outras condições, a placa já é inválida.
Então é exatamente isso que vamos fazer. Se a placa for inválida vamos retornar false
logo de cara. Isso se chama early return. Vamos refatorar nosso método usando essa técnica:
public static boolean validaPlaca(String placa){
placa = placa.replaceAll("[^a-zA-Z0-9]", "");
if(placa.length() != 7){
return false;
}
if(!placa.substring(0, 3).matches("[A-Z]*")){
return false;
}
return placa.substring(3).matches("[0-9]*");
}
Pronto, fizemos nosso método de forma elegante e enxuta.
Conclusão
Validar uma placa é uma tarefa simples, mas vários detalhes podem causar resultados inesperados. Temos, sempre, que prevenir nosso código, pois quando interagimos com o usuário, no nosso caso, recebendo informações vindas dele, não sabemos como o dado chegará para nós.
Também percebemos que não é necessário passar pelo método todo para ter o resultado esperado. Early return é uma boa prática de programação, pois impede que código desnecessário seja executado.
Agora que conhecemos o early return me digam vocês. Quantas vezes vocês já se depararam com códigos desnecessários sendo executados por não fazer uso de tal técnica?
Para conhecer outras técnicas e mais sobre boas práticas no Java, você pode dar uma olhada na Formação Java da Alura, lá você irá se deparar com vários cursos a respeito da linguagem.