
当通过重定向方式(如 `java main output.txt`)向java程序传入多行输入时,必须复用同一个scanner实例,否则后续方法新建scanner会因输入流已耗尽而抛出nosuchelementexception。
在Java中,System.in 是一个单次消费的输入流。一旦某个 Scanner 实例从 System.in 中读取并消耗了部分数据(例如调用 nextInt() 读取第一个整数),后续对该流的读取将从剩余位置继续;但如果在另一个方法中重新创建新的 Scanner(System.in) 实例,它并不会“重置”流指针,而是尝试再次读取——此时若原始流已被前一个Scanner提前关闭或内部缓冲已失效(尤其在JDK 9+中,Scanner 关闭时可能隐式关闭底层流),或更常见的是:前一个Scanner已读完可用输入但未触发EOF,新Scanner立即调用 nextInt() 就会因无有效token而抛出 NoSuchElementException。
上述问题的根本原因正是 read() 方法中独立创建了新的 Scanner(System.in),导致第二次读取失败。正确的做法是将Scanner作为参数显式传递,确保所有读取操作共享同一实例和同一输入流状态。
以下是修复后的完整代码:
import java.util.Scanner;
class Main {
public static int read(Scanner input) {
int num2 = input.nextInt();
System.out.println(num2);
return num2;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int num1 = input.nextInt();
System.out.println(num1);
read(input); // 复用同一Scanner实例
input.close(); // 推荐显式关闭,避免资源泄漏
}
}✅ 关键改进点:
立即学习“Java免费学习笔记(深入)”;
- read() 方法接收 Scanner 参数,不再自行创建;
- main 中统一管理Scanner生命周期,避免重复初始化;
- 最后调用 input.close()(虽非强制,但属良好实践,防止潜在资源占用)。
⚠️ 注意事项:
- 不要对 System.in 创建多个Scanner实例——这是常见陷阱;
- 若需在多个类/模块间共享输入源,可考虑将Scanner封装为工具类成员,或使用依赖注入;
- 对于更复杂的输入场景(如混合读取整数与字符串),注意 nextInt() 不会消耗换行符,后续调用 nextLine() 前需手动 input.nextLine() 清除缓冲,但本例中仅读整数,无需额外处理。
通过这种设计,程序能稳定、可靠地处理重定向输入,输出完全符合预期:1 和 2 各占一行。










