1. 概述

本文将深入解析 Java 中 java.util.Scanner 类的 nextLine() 方法,重点放在实际使用场景和一些容易踩坑的细节上。虽然这个方法看似简单,但在混合使用 next()nextLine() 时,很容易出问题,尤其是处理用户输入时。

2. Scanner.nextLine() 方法详解

nextLine() 的核心作用是:从当前扫描位置开始,读取直到遇到换行符为止的所有字符,并返回这一整行内容(不包含换行符本身)。

调用完成后,Scanner 的位置会移动到下一行的开头。

方法签名

public String nextLine()
  • ✅ 无参数
  • ✅ 返回值为当前行的字符串(不含换行符)
  • ❌ 如果输入流中没有更多行,抛出 NoSuchElementException
  • ❌ 如果 Scanner 已关闭,抛出 IllegalStateException

基本用法示例

下面是一个典型的使用场景:

try (Scanner scanner = new Scanner("Scanner\nTest\n")) {
    assertEquals("Scanner", scanner.nextLine());
    assertEquals("Test", scanner.nextLine());
}

这段代码会依次读取两行字符串。注意:\n 是换行符,Scanner 会将其识别为行分隔符。

扫描位置的影响

nextLine() 是从当前扫描位置开始读取的,而不是从行首。这一点在与其他方法(如 next())混用时特别关键。

看这个例子:

try (Scanner scanner = new Scanner("Scanner\n")) {
    scanner.useDelimiter(""); // 设置分隔符为空(按字符分割)
    scanner.next();           // 读取第一个字符 'S'
    assertEquals("canner", scanner.nextLine());
}

⚠️ 踩坑点:
虽然原始字符串是 "Scanner\n",但 next() 已经把 'S' 读走了,nextLine() 从剩下的 "canner\n" 开始读,直到换行符,所以结果是 "canner",不是 "Scanner"

这个行为在处理用户输入时非常常见,比如:

Scanner scanner = new Scanner(System.in);
System.out.print("请输入年龄:");
int age = scanner.nextInt(); // nextInt() 不会 consume 换行符

System.out.print("请输入姓名:");
String name = scanner.nextLine(); // 这里会立刻返回空字符串!

✅ 正确做法是:在 nextInt() 后手动调用一次 nextLine() 来“吃掉”残留的换行符:

int age = scanner.nextInt();
scanner.nextLine(); // 清除缓冲区中的换行符
String name = scanner.nextLine();

异常情况

nextLine() 可能抛出两种检查异常,使用时需注意:

1. NoSuchElementException

当输入流为空或已读完,再调用 nextLine() 时触发:

@Test(expected = NoSuchElementException.class)
public void whenReadingLines_thenThrowNoSuchElementException() {
    try (Scanner scanner = new Scanner("")) {
        scanner.nextLine(); // 输入为空,直接抛异常
    }
}

2. IllegalStateException

Scanner 已关闭后仍调用 nextLine()

@Test(expected = IllegalStateException.class)
public void whenReadingLines_thenThrowIllegalStateException() {
    Scanner scanner = new Scanner("hello");
    scanner.close();
    scanner.nextLine(); // 已关闭,抛异常
}

3. 总结

nextLine() 看似简单,但实际使用中容易因扫描位置未正确推进而导致逻辑错误,尤其是在混合使用 next()nextInt() 等方法时。

✅ 关键要点:

  • nextLine() 读取从当前位置到换行符的内容
  • 它会 consume 换行符,但其他 nextXxx() 方法通常不会
  • 读完基本类型后记得用 nextLine() 清理缓冲区
  • 注意空输入和关闭状态下的异常处理

示例代码已托管至 GitHub:https://github.com/dev-example/core-java-scanner


原始标题:Scanner nextLine() Method