Se você ficar lendo com o método nextInt() sempre existirá entrada a ser lida.
O método hasNext() lê a parte do stream que corresponde a tudo o que foi inserido, antes do "\n’ (enter, pressionado pelo usuário) (não é exatamente assim, mas, para fins didáticos, entenda assim).
Exemplo: você digita 100 e pressiona “enter”. O nextInt() lê o 100 e mantém o sinal do enter (\n).
Eu sugiro que leia com o nextLine() e converta o valor lido para inteiro.
Eu aprendi com meu amigo @drsmachado. Quando o mesmo dava aulas de programação java, logo após as primeiras aulas, quando ele ia apresentar as classes wrappers, ele fazia um exercício com esta pegadinha. Era parecido com isso:
Crie um programa java que leia o nome, a idade e o email de uma pessoa.
Obviamente, os alunos fariam algo como
public class LeDados{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("Digite seu nome");
String nome = sc.nextLine();//Aqui funciona ok
System.out.println("Digite sua idade");
int idade = sc.nexInt();//Aqui funciona ok
System.out.println("Digite seu email");
String email = sc.nextLine();//Aqui bugava
}
}
Note a ordem em que ele pedia que os dados fossem lidos: primeiro uma String, depois um int (podia ser um int, float, long, double, etc) e, novamente, uma String.
O que acontece é que, logo em seguida, ele explicava que a classe Scanner não tem um problema. Os métodos fazem o que foram programados para fazer. E só isso.
Daí ele pedia para ler todos os valores com o nextLine() e, então, apresentava as classes wrappers, mostrando que era possível ler String e converter para int, double, float, short, boolean…