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