A diferença no código está no método deleteInput(). Todo o resto é igual. A pergunta está no final, porque se trata da saída do console.
O código:
public class DeletePreviousInputs {
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws InterruptedException, IOException {
System.out.println("write something in the console");
/*
* What I wrote:
1 <enter> 2 <enter> 3 <enter> 4 <enter>
*/
Thread.currentThread();
Thread.sleep(8000); //simulates delay
deleteInput();
System.out.println("after input should be deleted");
System.out.println(scanner.nextLine());
System.out.println(scanner.nextLine());
System.out.println(scanner.nextLine());
}
//Version 1 of the deleteInput()-Method:
private static void deleteInput() throws InterruptedException {
try {
while (System.in.available() > 0) {
//This is the part, where the code will differ in Version 2
scanner.nextLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//Version 2 of the deleteInput()-Method:
private static void deleteInput() throws InterruptedException {
try {
while (System.in.available() > 0) {
//This is the part, where the code differs
Scanner dummyScanner = new Scanner(System.in);
dummyScanner.nextLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Versão de saída 1:
write something in the console
1
2
3
after input should be deleted
2
3
Versão de saída 2:
write something in the console
1
2
3
after input should be deleted
Por que a versão 1 não exclui/ignora todas as entradas anteriores? Por que a versão 2 funciona perfeitamente?
Tentei excluir todas as entradas anteriores de System.in para que apenas as mais recentes fossem reconhecidas pelo Scanner. Não esperava ver diferença na funcionalidade entre os dois métodos deleteInput(). Não entendo por que uma versão funciona e a outra não.
Atualizar:
@Sash (Não posso responder ao seu comentário por algum motivo, então atualizo aqui) Eu tentei e alterei apenas o método deleteInput() para isso:
System.out.println("deleteInput()-method has started");
while (scanner.hasNextLine()) {
scanner.nextLine();
}
System.out.println("deleteInput()-method has ended");
Mas isso cria um loop e o método nunca é encerrado. Aqui está a saída que recebo:
write something in the console
1
2
3
deleteInput()-method has started
Se eu substituir scanner.nextLine() por:
if(scanner.nextLine().isEmpty()) {
break;
}
ele também não sai do método.
Scanner
mantém seu próprio buffer. Quando você chamanextLine
, ele não lê necessariamente apenas uma linha. Ele tenta preencher seu buffer, lendo o máximo possível, e então retorna a primeira linha do buffer.Na versão 1,
deleteInput
,System.in.available() > 0
é inicialmente verdadeiro, e o scanner lê tudo (todas as 4 linhas) emSystem.in
, porque seu buffer é grande o suficiente. Na segunda iteração do loop,System.in.available() > 0
seria falso, porque agora tudo está no buffer do scanner.Depois
deleteInput()
, você usa o mesmo scanner para ler as linhas. Como o buffer do scanner ainda contém algumas linhas,readLine
retornará uma linha do buffer, em vez de ler oSystem.in
fluxo subjacente.Na versão 2, você usa um scanner diferente em
deleteInput
, então o buffer descanner
permanece vazio. Como resultado, oscanner.nextLine()
afterdeleteInput()
lerá deSystem.in
.Como alternativa ao uso de um
Scanner
, você também pode fazer:Observe que nem a versão acima nem a sua versão 2 pularão coisas que
scanner
já foram colocadas em seu buffer antes de você chamardeleteInput
. Por exemplo,Versão 1 de
deleteInput
scanner.nextLine()
retorna uma linha, mas consome toda a entrada disponívelSystem.out.println(scanner.nextLine())
tem algo a imprimir,Nota adicional:
System.in.available()
retorna0
após uma única chamada parascanner.nextLine()
, porque toda a entrada é consumida porscanner
Versão 2 de
deleteInput
dummyScanner
consome toda a entrada disponível.scanner.nextLine()
não tem nada a lerSystem.out.println(scanner.nextLine())
não produz nadaCódigo para ilustrar esse comportamento:
Na entrada:
A saída é: