
当通过重定向方式(如java main output.txt)向java程序传入多行输入时,必须复用同一个scanner实例,否则重复创建scanner会导致第二次读取时抛出nosuchelementexception异常。
在Java中,System.in是一个字节流(InputStream),其底层缓冲区在被Scanner封装后会按需读取并消费数据。关键点在于:每个Scanner实例都会独立维护对System.in的读取状态。当你在main()中创建一个Scanner input = new Scanner(System.in),它开始从标准输入流读取第一个整数;而紧接着在read()方法中再次执行new Scanner(System.in),会创建一个全新的Scanner——但此时System.in的内部指针已推进到第二行起始位置(或更后),且前一个Scanner可能已缓冲/消耗部分数据,导致新Scanner无法可靠定位,最终在调用nextInt()时因无有效token而抛出NoSuchElementException。
✅ 正确做法是将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实例
}
}? 注意事项:
- 不要在多个方法中各自new Scanner(System.in)——这是常见陷阱;
- 若需在深层调用链中读取,始终以参数形式传递Scanner,避免静态Scanner(易引发线程安全与资源泄漏问题);
- 使用完毕后,可在main末尾调用input.close()释放资源(尤其在处理大文件时);
- 对于更健壮的输入处理,建议配合hasNextInt()进行前置校验,避免运行时异常。
该方案简洁、可维护,并完全兼容输入重定向、管道及交互式输入场景。
立即学习“Java免费学习笔记(深入)”;










