ALGO25 / BLOG

Java: de ce nextLine pare să sară peste citire

Înțelege de ce nextLine pare să sară o linie după nextInt în Java. Urmărește poziția citirii și alege o strategie coerentă pentru text și numere.

Problema apare frecvent într-un formular de consolă: citești un număr cu nextInt, apoi un nume cu nextLine, iar numele pare gol. Scanner nu a pierdut textul. Cele două metode consumă unități diferite din flux și lasă cursorul în poziții diferite. Un token este un grup de caractere delimitat de separatori, precum spațiul sau terminatorul de linie.

Contractul exemplului

Exemplul folosește textul fix format din linia 2, apoi liniile ana și ion. Urmărim prima linie citită după număr și comparăm cu o versiune care citește toate câmpurile pe linii. Textul este local, iar cele două Scanner primesc copii independente ale aceleiași intrări.

Exemplu urmărit pas cu pas

nextInt citește tokenul 2, dar nu consumă terminatorul care urmează. Primul nextLine întoarce restul liniei curente, adică textul gol. Al doilea nextLine ajunge la ana. În versiunea pe linii, prima linie este convertită în număr, iar următorul nextLine citește direct ana.

nextInt citește tokenul 2, dar nu consumă terminatorul care urmează. Primul nextLine întoarce restul liniei curente, adică textul gol. Al doilea nextLine ajunge la ana. În versiunea pe linii, prima linie este convertită în număr, iar următorul nextLine citește direct ana.nextInt citește tokenul 2, dar nu consumă terminatorul care urmează.Mărește schema ↗

Cum funcționează soluția

Separă două strategii valide. Poți citi totul pe linii și interpreta ulterior numerele, cum face varianta corectată. Sau poți consuma intenționat restul liniei după tokenul numeric, dacă formatul garantează că acolo nu există alt câmp important. Alegerea trebuie făcută după format, nu prin adăugarea întâmplătoare a unor apeluri.

Program complet Java 21

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        String input = "2\nana\nion\n";
        Scanner mixed = new Scanner(input);
        int n = mixed.nextInt();
        System.out.println("n=" + n);
        System.out.println("prima=<" + mixed.nextLine() + ">");
        System.out.println("urmatoarea=<" + mixed.nextLine() + ">");
        Scanner lines = new Scanner(input);
        Integer.parseInt(lines.nextLine());
        System.out.println("corect=<" + lines.nextLine() + ">");
    }
}

Salvează programul în Main.java și compilează-l cu javac --release 21 Main.java, apoi rulează java Main. Exemplul include datele de verificare direct în program și nu cere intrare de la tastatură. Rezultatele prezentate mai jos nu depind de data calculatorului, de rețea sau de un serviciu extern.

Corectitudine și cost

Fiecare metodă citește exact tipul de unitate promis: nextInt un token numeric, nextLine restul liniei și separatorul ei. Eroarea este presupunerea că citirea tokenului a încheiat și linia. Costul citirii depinde de textul parcurs; schimbarea strategiei urmărește corectitudinea delimitării, nu o optimizare de performanță.

Capcana importantă

Dacă numele este pe aceeași linie după număr, un nextLine suplimentar care aruncă rezultatul poate pierde acel nume. Dacă linia goală este o valoare validă, nu o elimina automat printr-o buclă care sare toate liniile goale. Repararea trebuie să păstreze câmpurile pe care contractul le permite.

Exersează

Înlocuiește ana cu Ana Maria: citirea pe linii păstrează spațiul din nume. Pune apoi un spațiu după 2 înainte de terminator; primul rest de linie nu mai este gol, ci conține spațiul. În ambele cazuri, explică poziția cursorului înainte de fiecare apel, nu doar ieșirea observată.

Dacă sintaxa îți este nouă, începe cu primul program Java. Pentru structura prelucrării, reia tipurile, buclele și metodele. Pentru semnalarea intrărilor neacceptate, consultă excepțiile și colecțiile generice.

Comportamentul API este verificabil în documentația Java 21. Exemplele și explicațiile de aici folosesc contractul restrâns precizat mai sus.

Întrebări frecvente

nextInt consumă sfârșitul liniei?

Nu în sensul necesar următorului nextLine. Consumă tokenul numeric și lasă citirea la restul liniei curente, pe care nextLine îl poate întoarce chiar dacă este gol.

Este corect să adaug mereu un nextLine în plus?

Numai dacă formatul permite aruncarea restului liniei după număr. Dacă acel rest conține un câmp util, soluția pierde date. Citirea integrală pe linii oferă adesea un contract mai clar.

De ce nu folosim next pentru nume?

next citește un token și se oprește la separator. Pentru un nume care poate conține spații, precum Ana Maria, ai nevoie de citire pe linie sau de un format care descrie explicit câmpul.