Ler dados do teclado com a classe Scanner

No desenvolvimento em Java, a leitura de dados do teclado é uma tarefa comum, facilitada pela classe java.util.Scanner desde a versão 5. No entanto, iniciantes frequentemente enfrentam problemas com o salto de linha ao utilizar essa classe. Este tutorial abordará como solucionar esse problema específico, garantindo uma leitura de dados eficiente e sem complicações. Vamos explorar as melhores práticas e fornecer exemplos práticos para ajudar você a dominar o uso da classe Scanner em Java.

1. Criando a classe Teclado

Para iniciar o tutorial vamos criar a classe Teclado – Listagem 1 – com alguns atributos que serão preenchidos com os dados que serão capturados da leitura do teclado, mais o método toString() e main().

Listagem 1. Classe Teclado
package com.mballem.lerteclado;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Teclado {
    private long id;
    private String firstName;
    private String surname;
    private int age;

    @Override
    public String toString() {
        return "Teclado{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", surname='" + surname + '\'' +
                ", age=" + age +
                '}' + "\n";
    }

    public static void main(String[] args) {

    }
}

2. Lendo do teclado com Scanner

Agora será criado um método simples para a leitura de dados do teclado, nesse método vou apresentar também o problema do salto de linhas e algumas formas de resolvê-lo. Veja no método readingOne() – Listagem 2 – que o código aparentemente não apresenta problema algum.

Listagem 2. Método readingOne
package com.mballem.lerteclado;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Teclado {
    //atributos e toString() omitidos nesta listagem

    public static void main(String[] args) {
         readingOne();
    }

    private static void readingOne() {
        Scanner scanner = new Scanner(System.in);

        Teclado t = new Teclado();
        System.out.print("Enter your id: ");
        t.id = scanner.nextInt();
        System.out.print("Enter your first name: ");
        t.firstName = scanner.nextLine();
        System.out.print("Enter your last name: ");
        t.surname = scanner.nextLine();
        System.out.print("Enter your age: ");
        t.age = scanner.nextInt();

        System.out.println(t.toString());
    }
}

O código da Listagem 2 quando for executado vai resultar no problema exibido na Figura 1. Veja na marcação em vermelho que após o id ser informado, a linha first name não foi digitada e sim a linha surname. Isso aconteceu porque o método nextInt() da classe Scanner deixa no buffer a instrução da tecla pressionada, ou seja, um \n (123456789\n). Como o método nextInt() retorna apenas um valor inteiro, o \n acaba sendo adicionado ao próximo método que é o nextLine(). Assim, o método recebe uma instrução como se o usuário tivesse pressionado o e então pula para a próxima linha.

Figura 1 - Falha no método readingOne()

Figura 1 – Falha no método readingOne()

Uma forma para resolver esse problema é substituir o método nextLine() pelo método next(), como se pode observar na Listagem 3. Desta forma podemos ler perfeitamente as instruções conforme demonstrado na Figura 2.

Listagem 3. Método readingTwo
package com.mballem.lerteclado;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Teclado {
    //atributos e toString() omitidos nesta listagem

    public static void main(String[] args) {
         readingTwo();
    }

    private static void readingTwo() {
        Scanner scanner = new Scanner(System.in);

        Teclado t = new Teclado();
        System.out.print("Enter your id: ");
        t.id = scanner.nextInt();
        System.out.print("Enter your first name: ");
        t.firstName = scanner.next();
        System.out.print("Enter your last name: ");
        t.surname = scanner.next();
        System.out.print("Enter your age: ");
        t.age = scanner.nextInt();

        System.out.println(t.toString());
    }
}
Figura 2 - Método readingTwo()

Figura 2 – Método readingTwo()

Mas ainda temos um problema, o método next() não permite que se use, por exemplo, o espaço entre palavras. Se for digitado algo como “João Luiz” o método irá separar o nome “João” de “Luiz”, veja o acontece na Figura 3. Observe que na marcação em vermelho, após ter sido digitado o nome “João Luiz” a linha seguinte foi saltada, indo direto para a próxima linha. Porém, quando foi impresso o objeto, o nome “Luiz” apareceu no atributo surname, o que não deveria ter acontecido.

Figura 3 - Falha ocorrida em readingTwo

Figura 3 – Falha ocorrida em readingTwo

Uma forma para resolver de vez esse problema do salto de linhas é usar apenas o método nextLine(), mesmo que um atributo não seja do tipo String. Bastaria apenas fazer a conversão de tipos, como descrito na Listagem 4. Confira na Figura 4 o resultado da execução do método readingThree().

Listagem 4. Usando apenas o nextLine()
package com.mballem.lerteclado;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Teclado {
    //atributos e toString() omitidos nesta listagem

    public static void main(String[] args) {
         readingThree();
    }

    private static void readingThree() {
        Scanner scanner = new Scanner(System.in);

        Teclado t = new Teclado();
        System.out.print("Enter your id: ");
        t.id = Long.parseLong(scanner.nextLine());
        System.out.print("Enter your first name: ");
        t.firstName = scanner.nextLine();
        System.out.print("Enter your last name: ");
        t.surname = scanner.nextLine();
        System.out.print("Enter your age: ");
        t.age = Integer.parseInt(scanner.nextLine());

        System.out.println(t.toString());
    }
}
Figura 4 - Problemas resolvidos

Figura 4 – Problemas resolvidos

Você pode agora criar um menu pelo teclado, como exemplo veja a Listagem 5.

Listagem 5. Criando um menu com a classe Scanner
package com.mballem.lerteclado;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Teclado {
    //atributos e toString() omitidos nesta listagem

    public static void main(String[] args) {
         readingMenu();
    }

    private static void readingMenu() {
        Scanner scanner = new Scanner(System.in);
        Teclado t;
        List list = new ArrayList();
        int option = 0;
        do {
            System.out.println("1. Add User");
            System.out.println("2. Print Users");
            System.out.println("0. Exit");
            System.out.print("> ");
            option = Integer.parseInt(scanner.nextLine());
            if (option == 1) {
                t = new Teclado();
                System.out.print("Enter your id: ");
                t.id = Long.parseLong(scanner.nextLine());
                System.out.print("Enter your first name: ");
                t.firstName = scanner.nextLine();
                System.out.print("Enter your last name: ");
                t.surname = scanner.nextLine();
                System.out.print("Enter your age: ");
                t.age = Integer.parseInt(scanner.nextLine());
                list.add(t);
            } else if (option == 2) {
                System.out.println(list.toString());
            }
        } while (option != 0);
    }
}

Conclusão

Neste tutorial, exploramos como utilizar a classe Scanner para ler dados do teclado em Java, identificando e resolvendo o problema comum do salto de linha. Vimos como os métodos nextInt() e nextLine() podem causar confusões e como substituí-los apropriadamente por next() ou nextLine() com conversão de tipos. Com os exemplos práticos fornecidos, você agora pode implementar uma leitura de dados mais robusta e eficiente em seus projetos Java. Dominar essas técnicas é essencial para evitar erros comuns e garantir a precisão da entrada de dados no seu aplicativo.

Saiba mais

Ballem

Marcio Ballem é bacharel em Sistemas de Informação pelo Centro Universitário Franciscano em Santa Maria/RS. Tem experiência com desenvolvimento Delphi e Java em projetos para gestão pública e acadêmica. Possui certificação em Java, OCJP 6.

Você pode gostar...