Esto es de la explicación del método next () de Scanner de Java:

Este método puede bloquearse mientras espera la entrada para escanear, incluso si una invocación previa de hasNext () devuelve verdadero.

¿Cómo puede este método esperar a que se ingrese la entrada del usuario si se realiza una llamada a hasNext ()? Si llamamos a hasNext () y devuelve verdadero, sabemos que existe el siguiente token, entonces, ¿cómo y por qué el método next () hace esto?

1
LearningMath 22 oct. 2017 a las 00:11

3 respuestas

La mejor respuesta

Debe leer el completo documentación del método:

Encuentra y devuelve el siguiente token completo de este escáner. UNA el token completo va precedido y seguido de una entrada que coincide con el patrón delimitador . Este método puede bloquearse mientras espera la entrada para exploración, incluso si una invocación previa de hasNext () devuelve verdadero.

El método Scanner#hasNext (documentación) puede devolver true cuando hay otro token. Pero podría ser posible que el token aún no se considere como completo de acuerdo con el patrón delimitador y Scanner#next siempre se bloqueará hasta que el token esté completo.

Si hay un token completo en Scanner, entonces Scanner#next volverá inmediatamente y no se bloqueará .


Puede establecer el patrón delimitador utilizando el método Scanner#useDelimiter (documentación)

Si no establece un patrón de delimitador específico, Scanner utilizará un patrón predeterminado que coincida con caracteres de espacio en blanco .


Como ha pedido, bloqueado significa que el método espera y no regresa hasta que dicho evento sucedió.

Considere esto:

System.out.println("Before");
someBlockingMethod();
System.out.println("After");

Con

public void someBlockingMethod() {
    // Sleep for a second (ignoring exceptions for simplicity)
    Thread.sleep(1000);
}

Verá After solo una vez que someBlockingMethod() haya regresado y esto solo sucederá una vez que ocurra dicho evento. Por lo tanto, el método bloquea . En el ejemplo, el método bloquea durante un segundo.

2
Zabuzard 21 oct. 2017 a las 21:40

Scanner#next no devuelve una cadena hasta que haya alcanzado el delimitador utilizado por Scanner (el espacio en blanco es el delimitador predeterminado) o haya llegado al final del flujo de entrada.

Si hasNext devuelve verdadero, significa que definitivamente hay más datos en la secuencia de entrada, pero aún puede necesitar bloquearse hasta que llegue al delimitador / EOF.

1
4castle 21 oct. 2017 a las 21:19

Si depura el siguiente código, verá que, en realidad, es el método hasNext () el que está bloqueando y esperando la entrada del usuario:

Scanner scanner = new Scanner(System.in);
if (scanner.hasNext()) {
    String s = scanner.next();
}

Eso es porque hay un paso de bloqueo dentro de hasNext ():

public boolean hasNext() {
    ensureOpen();
    saveState();
    while (!sourceClosed) {
        if (hasTokenInBuffer())
            return revertState(true);
        readInput(); //THIS IS WAITING FOR USER INPUT
    }
...

En el caso de la entrada de la consola, hasNext () espera hasta que se ingrese un token completo y devuelve verdadero, luego la siguiente invocación next () no se bloquea.

En caso de entrada que no sea de consola, hasNext () devuelve verdadero incluso si no hay token completo, y los bloques de invocación next () posteriores y espera token completo.

1
elyor 21 oct. 2017 a las 22:02