Para ler entradas do teclado, ainda mais nos casos em que você mistura leitura de números e strings, é melhor usar nextLine
.
Por exemplo, se começarmos digitando o nome “Fulano de Tal”, next()
só irá ler “Fulano”, e ao chamar nextInt()
depois, ele irá ler “de” e tentar converter para número, e dará erro. Enfim, tem várias outras situações que podem dar problema, prefira usar somente nextLine
e depois converter a linha para o tipo que precisa (inteiro, double
, etc).
Tem também isso:
sexo.toLowerCase();
Em Java strings são imutáveis, então métodos como toLowerCase()
não modificam a string. Na verdade eles retornam outra string, então a linha acima só chama o método, mas o retorno é perdido. O certo seria jogar em uma variável (podendo ser inclusive a mesma):
sexo = sexo.toLowerCase();
Ou ainda:
sexo = scan.nextLine().toLowerCase();
E também dá pra remover algumas repetições criando métodos, como por exemplo:
public static String lerString(Scanner scan, String prompt, List<String> valoresValidos) {
while (true) {
System.out.println(prompt);
String valor = scan.nextLine().toLowerCase();
if (valoresValidos.contains(valor)) {
return valor;
} else {
System.out.println("Valores válidos: " + String.join(", ", valoresValidos));
}
}
}
Aí no main
bastaria fazer:
String sexo = lerString(scan, "Entre com seu genero/sexo ", Arrays.asList("m", "f"));
String estadoCivil = lerString(scan, "Entre com seu Estado Civil", Arrays.asList("s", "c", "v", "d"));
Para os demais, não sei se compensa fazer algo mais complicado e generalizado. Talvez seja exagero para um exercício, mas enfim, daria para ter algo assim (obs: o código abaixo usa recursos que só funcionam a partir do Java 8):
// imports
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
//-----------------------------------------------------
// versão que recebe um validador
public static <T> T lerDados(Scanner scan, String prompt, Function<String, T> conversor, Predicate<T> validador, String mensagemErro) {
// passa o validador, e a lista de valores válidos é nula
return lerDados(scan, prompt, conversor, validador, null, mensagemErro);
}
// versão que recebe a lista de valores válidos
public static <T> T lerDados(Scanner scan, String prompt, Function<String, T> conversor, List<T> valoresValidos) {
// não tem validador, então usa a lista de valores válidos (e a mensagem de erro será construída a partir dos valores válidos)
return lerDados(scan, prompt, conversor, null, valoresValidos, "");
}
private static <T> T lerDados(Scanner scan, String prompt, Function<String, T> conversor, Predicate<T> validador,
List<T> valoresValidos, String mensagemErro) {
while (true) {
// mostra a mensagem
System.out.println(prompt);
// lê os dados
String line = scan.nextLine().toLowerCase();
try {
// converte para o tipo desejado
T valor = conversor.apply(line);
// verifica se é válido
if (validador != null) { // se tem validador, usa
if (validador.test(valor)) {
return valor; // válido, retorna
} else {
System.out.println(mensagemErro);
}
} else if (valoresValidos != null && valoresValidos.size() > 0) {
// se tem valores válidos, verifica se é um deles
if (valoresValidos.contains(valor)) {
return valor;
} else {
System.out.println("Valores válidos: " + String.join(", ", valoresValidos.stream().map(v -> v.toString()).collect(Collectors.toList())));
}
} else {
// se não tem validador e nem lista de valores válidos, não tem o que validar
// então assume-se que o valor é válido
return valor;
}
} catch (Exception e) {
System.out.println(mensagemErro);
}
}
}
E no main
ficaria:
Scanner scan = new Scanner(System.in);
String nome = lerDados(scan, "Entre com seu nome", Function.identity(), s -> s.length() >= 3, "Entre com mínimo de 3 caracteres");
int idade = lerDados(scan, "Entre com sua idade", Integer::parseInt, n -> n >= 0 && n <= 150, "Entre com valores entre 0 e 150");
double salario = lerDados(scan, "Entre com seu salario ", Double::parseDouble, n -> n > 0, "Entre com valores acima de 0: ");
String sexo = lerDados(scan, "Entre com seu genero/sexo ", Function.identity(), Arrays.asList("m", "f"));
String estadoCivil = lerDados(scan, "Entre com seu Estado Civil", Function.identity(), Arrays.asList("s", "c", "v", "d"));
Mas novamente: pra um exercício simples, provavelmente é exagero…
Outro detalhe é que não precisa fechar o System.in
. Pra programas simples assim não faz diferença, mas enfim…