Quando você usa um bloco try
desta maneira, ele já fecha automaticamente o recurso criado, então chamar scanner.close()
novamente é desnecessário. Mas no caso específico do System.in
, não se deve fechá-lo, então eu não usaria o bloco try-with-resources com o System.in
.
Essa condição do while
está errada, e só “funciona” porque na opção 3 você coloca um return
, que encerra a execução do método main
(experimente tirar o return
para ver como ele não encerra o loop).
Na verdade deveria ser apenas while (opcao != 3)
, já que a única condição para encerrar o while
é quando a opção é 3, então qualquer valor diferente disso deve continuar o loop.
Outro detalhe é que se está lendo dados digitados pelo teclado, é preferível usar nextLine()
. Usar next()
não pega a linha inteira: por exemplo, se o usuário digitar “banana nanica”, next()
retorna apenas “banana”, e “nanica” será lido pelo próximo next()
(que será passado para Integer.parseInt
, dando erro).
E no caso do número, é completamente desnecessário usar toUpperCase()
(pois se digitar um número válido, como “123”, não fará diferença nenhuma transformar para maiúsculas).
E eu também mudaria a forma como está usando a classe Fruta
. Aí em cima sugeriram mudar um pouco, o que já melhorou bastante, mas eu ainda acho estranho a fruta ter a própria quantidade dela. Uma fruta tem só o nome dela, já a quantidade não faz parte da fruta, e sim do estoque (diferentes estoques podem ter quantidades diferentes da mesma fruta).
Claro que a implementação depende dos requisitos de cada sistema, mas eu entendo que a fruta é uma coisa independente da quantidade desta, então faria mais sentido ter uma outra classe que cuida do estoque. Uma implementação simples seria:
public class Fruta {
private String nome;
public Fruta(String nome) {
this.nome = nome;
}
public String getNome() {
return nome;
}
// equals e hashcode para poder usar a fruta no Map do Estoque
@Override
public int hashCode() {
return Objects.hash(this.nome);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof Fruta))
return false;
Fruta other = (Fruta) obj;
return this.nome.equals(other.nome);
}
}
public class Estoque {
private Map<Fruta, Integer> frutas = new HashMap<>();
public void adicionar(Fruta fruta, int quantidade) {
// obtém a quantidade atual da fruta, ou zero se ainda não estiver no estoque
int qtdAtual = this.frutas.getOrDefault(fruta, 0);
// atualiza a quantidade
this.frutas.put(fruta, quantidade + qtdAtual);
}
public void listar() { // mostrar as frutas e respectivas quantidades
System.out.println("Frutas:");
for (Entry<Fruta, Integer> entry : this.frutas.entrySet()) {
System.out.printf(" - %s | %d\n", entry.getKey().getNome(), entry.getValue());
}
}
}
Quanto ao while
, eu faria diferente. Eu prefiro um loop infinito que é interrompido por um break
. Juntando com as classes Fruta
e Estoque
acima:
Scanner scanner = new Scanner(System.in);
Estoque estoque = new Estoque();
while (true) {
System.out.print("Digite a opção de acordo com o que deseja fazer!\n"
+ "1 --> Cadastrar fruta\n"
+ "2 --> Consultar frutas cadastradas\n"
+ "3 --> Encerrar\n");
int opcao = Integer.parseInt(scanner.nextLine());
if (opcao == 3) {
System.out.println("Encerrando...\n");
break; // sai do while
} else if (opcao == 1) {
System.out.println("Informe o nome da fruta:");
String nomeFruta = scanner.nextLine().toUpperCase();
System.out.println("Informe a quantidade de frutas deste tipo:");
int qtdFruta = Integer.parseInt(scanner.nextLine());
estoque.adicionar(new Fruta(nomeFruta), qtdFruta);
System.out.println("\n");
} else if (opcao == 2) {
estoque.listar();
} else {
System.out.println("Opção Inválida!\n");
}
}
Claro que dá para melhorar mais. Se for digitado uma opção que não é um número (por exemplo, “xyz”), vai dar erro. Então talvez possa ter um método só para validar isso, algo do tipo:
static int lerNumero(Scanner scanner) {
while (true) {
try {
return Integer.parseInt(scanner.nextLine());
} catch (NumberFormatException e) {
System.out.println("Você não digitou um número");
}
}
}
E no main
basta mudar para:
Scanner scanner = new Scanner(System.in);
Estoque estoque = new Estoque();
while (true) {
System.out.print("Digite a opção de acordo com o que deseja fazer!\n"
+ "1 --> Cadastrar fruta\n"
+ "2 --> Consultar frutas cadastradas\n"
+ "3 --> Encerrar\n");
int opcao = lerNumero(scanner); // <------ usar o método aqui
if (opcao == 3) {
System.out.println("Encerrando...\n");
break; // sai do while
} else if (opcao == 1) {
System.out.println("Informe o nome da fruta:");
String nomeFruta = scanner.nextLine().toUpperCase();
System.out.println("Informe a quantidade de frutas deste tipo:");
int qtdFruta = lerNumero(scanner); // <------ usar o método aqui
estoque.adicionar(new Fruta(nomeFruta), qtdFruta);
System.out.println("\n");
} else if (opcao == 2) {
estoque.listar();
} else {
System.out.println("Opção Inválida!\n");
}
}