不能混用 BufferedReader 和 Scanner,因为二者内部缓冲机制不同,会相互干扰导致数据丢失、阻塞或跳过输入;推荐统一使用其一,并按需解析字符串。

通常不建议把 BufferedReader 和 Scanner 一起用于同一个输入源(比如 System.in),因为它们会相互干扰——两者都尝试消费输入流,容易导致数据丢失、阻塞或跳过输入。
为什么不能混用 BufferedReader 和 Scanner?
BufferedReader 和 Scanner 都基于 System.in,但内部缓冲机制不同:
-
Scanner内部自带缓冲区,并会预读、解析(如跳过空白、按分隔符切分); -
BufferedReader按行或字符块读取,不解析内容; - 若先用
Scanner.nextLine(),再用BufferedReader.readLine(),后者很可能立即返回空字符串(因为换行符已被 Scanner 消费); - 反过来也一样:BufferedReader 读走一行后,Scanner 可能从下一行开始,漏掉中间内容。
什么时候需要“灵活读取”?常见场景及推荐方案
所谓“灵活”,通常指既要读整行(含空格),又要读单个词、数字、甚至混合类型。这不是靠组合两个类解决的,而是选对工具 + 合理设计:
-
纯文本行输入(含空格) → 用
BufferedReader.readLine()最高效、最可靠; -
解析结构化输入(如 “张三 25 true”) → 用
Scanner更方便(next(),nextInt(),nextBoolean()等); -
混合需求(先读一行,再从中提取数字) → 用
BufferedReader读整行,再用Scanner包装该字符串解析:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = br.readLine(); // 安全读取完整一行 Scanner scLine = new Scanner(line); String name = scLine.next(); int age = scLine.nextInt(); boolean active = scLine.nextBoolean();
替代方案:只用 Scanner 实现“类 BufferedReader”的能力
Scanner 其实也能读整行(nextLine()),只要注意它和 nextXxx() 方法之间的换行符冲突:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 调用
nextInt()或next()后,输入流停在换行符前; - 紧接着调用
nextLine()会立刻返回空字符串(读到那个残留换行符); - 解决方法:在
nextXXX()后加一句sc.nextLine()吸收换行符。
Scanner sc = new Scanner(System.in);
System.out.print("年龄:");
int age = sc.nextInt();
sc.nextLine(); // 吸收换行符
System.out.print("姓名:");
String name = sc.nextLine(); // 这里才能正确读到下一行
真正需要高性能时怎么办?
如果程序频繁读取大量控制台输入(少见),BufferedReader 确实比 Scanner 快。此时建议:
- 统一用
BufferedReader; - 对读到的每行字符串,用
String.split()、正则或StringTokenizer解析; - 数字转换用
Integer.parseInt()、Double.parseDouble()等; - 避免在循环中反复创建
Scanner对象(开销小但非必要)。
不复杂但容易忽略:选一个主读取器,按需处理字符串,而不是强行桥接两个流包装器。

















