如何在Java命令行程序中正确复用标准输入流处理多个方法调用

碧海醫心

碧海醫心

2026-01-27

444人浏览

原创

如何在Java命令行程序中正确复用标准输入流处理多个方法调用

当通过重定向(如 `java main

在Java中,System.in 是一个字节流(InputStream),其底层资源(如文件句柄)是共享且不可重复打开的。虽然多次构造 new Scanner(System.in) 语法上合法,但每个 Scanner 实例会独立尝试从同一输入流中读取数据——而一旦前一个 Scanner 已消费了部分输入(例如调用 nextInt() 读走第一个整数),后续 Scanner 在初始化或首次调用扫描方法时,可能因流已关闭、缓冲区耗尽或内部状态不一致而立即失败,典型表现就是 NoSuchElementException。

根本原因在于:Scanner 并非简单“指向”System.in,而是对其进行了缓冲和状态管理。多个 Scanner 实例竞争同一输入源,破坏了读取的原子性和顺序性,尤其在重定向场景下(输入来自文件而非交互终端)更为敏感。

✅ 正确解法是全局复用单个 Scanner 实例,并通过方法参数显式传递:

度加AI
度加AI

度加AI官网入口,百度官方 AIGC 创作平台,支持 AI 成片、AI 生文、数字人、声音克隆、配音字幕与智能剪辑等在线创作能力。

下载
import java.util.Scanner;

class Main {
    // 将 Scanner 作为参数传入,避免重复创建
    public static int read(Scanner input) {
        int num2 = input.nextInt();
        System.out.println(num2);
        return num2;
    }

    public static void main(String[] args) {
        // 在 main 中创建唯一 Scanner 实例
        Scanner input = new Scanner(System.in);
        int num1 = input.nextInt();
        System.out.println(num1);
        read(input); // 复用同一实例
        input.close(); // 建议显式关闭,释放资源
    }
}

? 关键要点:

  • 不要在多个方法中各自 new Scanner(System.in) —— 这是绝大多数此类错误的根源;
  • 始终将 Scanner 作为参数传递,确保所有读取操作共享同一缓冲区与游标位置;
  • 在使用完毕后调用 scanner.close()(尤其在处理文件重定向时),防止资源泄漏(注意:关闭 Scanner 也会关闭其底层 System.in,但在标准输入重定向场景中通常无副作用;若需多次复用,可省略关闭,JVM 退出时自动释放);
  • 若逻辑复杂,也可将 Scanner 声明为 static 字段(不推荐用于多线程环境),但参数传递更清晰、更易测试、更符合面向对象设计原则。

运行命令 java Main output.txt 后,程序将稳定输出:

1
2

完全符合预期,且无异常。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java 字节 stream

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

2025.09.05

2032

14

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.27

153

13

C++ 面向对象编程与设计模式实践
C++ 面向对象编程与设计模式实践

本专题整合了 C++ 面向对象编程的核心机制,涵盖类的定义与访问控制、构造函数与析构函数、拷贝语义与移动语义、继承与虚函数多态、抽象类与接口、运算符重载、友元函数等关键知识点,同时结合单例模式、工厂模式、观察者模式、策略模式等常用设计模式的 C++ 实现,帮助开发者写出结构清晰、易于维护的面向对象代码。

2026.04.09

91

30

Java 面向对象与核心编程机制
Java 面向对象与核心编程机制

系统讲解 Java 面向对象编程的核心知识体系,涵盖类的定义与封装、构造方法与 this/super 关键字、继承与方法重写、多态与向上向下转型、抽象类与接口的区别与设计原则、异常处理机制(try-catch-finally / 自定义异常)、泛型的类型参数与通配符、集合框架(List/Set/Map)的使用与遍历方式,帮助开发者全面掌握 Java 程序设计的核心机制与面向对象思维。

2026.04.17

81

15

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

2094

6

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

2025.12.24

618

20

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

2026.01.21

129

30

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

2026.01.21

315

24

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

2026.02.06

202

20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

Java 26官方文档
Java 26官方文档

共0课时 | 0人学习