Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Comparilhando um comportamento estranho da classe Scanner.

Alguns posts atrás, compartilhei meu código Java do projeto da Conta Bancária. Acontece que descobri um bug devido a um comportamento estranho do Scanner.

O código era este para a opção 5:

if (opcao == 5){
               
               double valorPix = 0;
               System.out.println("Digite a chave pix do destinatário:");
               String chavePix = leitura.next();
               System.out.println("Digite o nome do destinatário");
               
               String nomeDestinatario = leitura.next(); //LOCAL DO BUG
               
               System.out.println("Digite um valor para o pix:");
               valorPix = leitura.nextDouble();
               //Bloco condicional secundário
               if (valorPix <= saldo) {
                   saldo -= valorPix;
                   System.out.println("""
                   Pix realizado com sucesso para:
                   Nome: %s
                   Chave pix: %s
                   """.formatted(nomeDestinatario, chavePix));
                   System.out.println("Seu saldo atual é de: R$ " + saldo);
               }else {
                   System.out.println("Saldo insuficiente para esta operação.");
               }
           }

Por algum motivo, o Scanner lia a primeira entrada (chave pix) e lia apenas a primeira palavra da segunda entrada (nome do destinatário), fazendo com que a segunda palavra ficasse armazenada e fosse lida na próxima entrada (valor, que na verdade é um nextDouble(), causando um erro). Descobri isso por que testei colocar nomes com apenas uma palavra para o destinatário e o erro desaparecia. O motivo de eu optar pelo next, foi pq o nextLine() também tinha um comportamento estranho. Neste último caso, o Scanner não lia a primeira entrada (chavePix). Assim, a chave pix recebia uma string vazia. Pesquisei na doc do Java e descobri que o nextLine pula uma linha. Nâo entendi bem como isso funciona. Então, para o meu código funcionar, fiz a seguinte alteração:

if (opcao == 5){
               
               double valorPix = 0;
               System.out.println("Digite a chave pix do destinatário:");
               
               String chavePix = leitura.nextLine() + leitura.nextLine(); // LOCAL DA ALTERAÇÃO
               
               System.out.println("Digite o nome do destinatário");
               String nomeDestinatario = leitura.nextLine();
               System.out.println("Digite um valor para o pix:");
               valorPix = leitura.nextDouble();
               //Bloco condicional secundário
               if (valorPix <= saldo) {
                   saldo -= valorPix;
                   System.out.println("""
                   Pix realizado com sucesso para:
                   Nome: %s
                   Chave pix: %s
                   """.formatted(nomeDestinatario, chavePix));
                   System.out.println("Seu saldo atual é de: R$ " + saldo);
               }else {
                   System.out.println("Saldo insuficiente para esta operação.");
               }
           }

Fiquei em dúvida sobre por que isso acontece e se existe outra maneira de solucionar o problema. Desde já, muito obrigado.

1 resposta
solução!

Olá, Elcidio! Joia?

Esse comportamento do Scanner realmente pode ser um pouco confuso no início. O que acontece é que o método next() lê a próxima palavra (delimitada por espaço) e o método nextLine() lê a linha inteira até encontrar um caractere de nova linha (enter).

Quando você usa nextLine() após um next(), o nextLine() pode acabar lendo o caractere de nova linha deixado pelo next(), resultando em uma string vazia. É por isso que você encontrou o comportamento estranho.

Para resolver isso de maneira mais limpa, você pode adicionar um nextLine() extra após o next() para consumir o caractere de nova linha residual. Aqui está como você pode ajustar seu código:

if (opcao == 5) {
    double valorPix = 0;
    System.out.println("Digite a chave pix do destinatário:");
    String chavePix = leitura.next(); // Lê a chave pix
    leitura.nextLine(); // Consome o caractere de nova linha residual

    System.out.println("Digite o nome do destinatário");
    String nomeDestinatario = leitura.nextLine(); // Agora lê a linha inteira corretamente

    System.out.println("Digite um valor para o pix:");
    valorPix = leitura.nextDouble();

    // Bloco condicional secundário
    if (valorPix <= saldo) {
        saldo -= valorPix;
        System.out.println("""
        Pix realizado com sucesso para:
        Nome: %s
        Chave pix: %s
        """.formatted(nomeDestinatario, chavePix));
        System.out.println("Seu saldo atual é de: R$ " + saldo);
    } else {
        System.out.println("Saldo insuficiente para esta operação.");
    }
}

Neste ajuste, após ler a chavePix com next(), adicionamos um leitura.nextLine() para consumir o caractere de nova linha que ficou no buffer. Isso garante que o próximo nextLine() funcione corretamente e leia a linha inteira do nome do destinatário.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.