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.