Java标准输入输出流(System.in、System.out、System.err)由JVM启动时绑定操作系统底层资源,生命周期与进程一致,不能显式关闭,否则后续操作抛IOException且不可恢复。
Java标准输入输出流(System.in、System.out、System.err)本质上是预初始化的全局流对象,**不能被显式关闭,也不支持重置**。强行调用 close() 会导致后续使用抛出 IOException,且无法“重新打开”——这不是设计缺陷,而是语义约束。
这些流由 JVM 在启动时绑定到操作系统底层资源(如终端、控制台),其生命周期与 JVM 进程一致。调用 System.in.close() 实际上会关闭底层文件描述符(如 stdin 的 fd 0),之后任何对 System.in 的读取操作都会失败,且 JVM 不提供重建该连接的机制。
BufferedInputStream,也不维护内部缓冲区,调用 markSupported() 返回 false;new FileInputStream(FileDescriptor.in) 的安全方式(因为 FileDescriptor.in 在关闭后已失效);println() 等操作会抛异常,且影响所有依赖它的日志、框架输出。当需要多次读取用户输入(例如解析命令、重试输入),不能依赖 System.in.reset(),而应采用**数据缓存 + 逻辑复用**策略:
Scanner(System.in) 或 BufferedReader(new InputStreamReader(System.in)) 读取整行或整块,存入 String 或 byte[],后续从内存中反复解析;InputStream 接口,可将原始输入内容转为 ByteArrayInputStream,它天然支持 mark()/reset();InputStream 参数而非硬编码 System.in,便于测试和重用(例如单元测试时传入 new ByteArrayInputStream("test".getBytes()))。真正需要调用 close() 的,是**你主动创建的、非标准的流实例**,比如:
立即学习“Java免费学习笔记(深入)”;
new FileInputStream("data.txt") 打开的文件流;new BufferedInputStream(System.in) 包装后的流(注意:这包装的是副本,关闭它不影响 System.in 原始引用,但一般也不建议包装标准输入并关闭);System.setIn(...) 替换后的自定义输入流——此时你负责管理其生命周期。对于这些流,务必使用 try-with-resources 或 finally 块确保关闭,防止文件句柄泄漏。
若用 System.setIn(new FileInputStream("input.txt")) 重定向了标准输入,那么:
System.in 后);System.in(键盘)未被关闭,只是暂时不可达;