Problema sem fim em loop com try / catch

Eu tenho um loop while que deve capturar uma input não-int e pedir ao usuário para re-inserir um int. No entanto, apenas interminavelmente a mensagem de erro. Alguém tem uma idéia porque não é não permitir a input do scanner pela segunda vez?

while(!enteredInt) { try { locus = input.nextInt(); enteredInt = true; } catch (Exception e) { //user didn't type an integer System.out.println("You didn't enter a valid number, re-enter point where you will build your city"); } } 

Quando você insere um token que não é um número, chamar nextInt não move o scanner além do token. Como resultado, é só ler o mesmo token repetidamente.

Aqui está a documentação do nextInt: http://download.oracle.com/javase/6/docs/api/java/util/Scanner.html#nextInt%28%29 (embora o comportamento relevante seja realmente descrito na versão que leva um argumento, aqui: http://download.oracle.com/javase/6/docs/api/java/util/Scanner.html#nextInt%28int%29 )

Então, para dar um exemplo rápido, vamos supor que a string de input seja "1 2 Foo" . Eu adicionarei um X para mostrar onde o Scanner está atualmente posicionado. Começa "X1 2 Foo" . Então a primeira chamada para input.nextInt() acontece. Ele retorna 1 e agora estamos em "1 X2 Foo" . Em seguida, a segunda chamada para input.nextInt() acontece. Ele retorna 2 e agora estamos em "1 2 XFoo" . Em seguida, a terceira chamada para input.nextInt() acontece. Ele não retorna, mas lança um InputMismatchException e também não avança o Scanner. Então ainda estamos em "1 2 XFoo" . Então, quando a chamamos pela quarta ou quinta vez, a mesma coisa acontece.

Para resolver esse problema, uma chamada input.next() consumirá o próximo token, seja ele qual for. Após esta chamada, no nosso exemplo, estaríamos em "1 2 FooX" .

Observe, no entanto, que a chamada para input.next() também pode lançar exceções. Especificamente, ele pode lançar IllegalStateException se o Scanner estiver fechado (o que não deveria acontecer no seu código) ou NoSuchElementException se o Scanner atingir o final da input (o que não acontecerá se você estiver lendo do teclado, como eu suponha que você é). Mas apenas para estar seguro, você deve pegar esses erros e sair do loop ou não pegá-los e, em vez disso, declará-los como lançados pelo seu método.

Conforme declarado na documentação:

Quando um scanner lança um InputMismatchException, o scanner não passará o token que causou a exceção, para que ele possa ser recuperado ou ignorado por algum outro método.

Portanto, o mesmo token (não inteiro) continuará jogando a exceção.

Você pode usar o método next () para recuperar esse token dentro da captura.