一文掌握 Java 键盘输入:从入门到高阶(含完整示例与避坑指南)
摘要:本文系统讲解 Java 中的键盘输入。围绕 System.in 的三条主线 —— Scanner、BufferedReader + InputStreamReader、Console —— 从原理、用法、编码与本地化、常见坑到测试与封装,帮助你在各种场景下正确、稳健地处理输入。
一、为何要理解“键盘输入”的底层模型
-
底层只有一个输入源: ystem.in,类型是 InputStream(字节流)。
-
字符与字节的桥梁: 文本输入需要通过 字符集解码 才能得到 char/String。
-
API 的差异:
-
Scanner:易用,自动分隔并解析。
-
BufferedReader:高效,逐行读取,可控性强。
-
Console:增强交互体验,支持密码输入。
理解这些,能帮你在不同场景下选择合适的方案。
二、三种主流方案概览
方案 | 核心类 | 优点 | 适用场景 | 注意点 |
---|---|---|---|---|
Scanner | java.util.Scanner | 上手快,支持各种类型 | 日常开发、教学作业 | 正则切分偏慢;行尾换行问题 |
BufferedReader | BufferedReader + InputStreamReader | 高效,编码可控 | 性能敏感、大量输入 | 需手动解析数字 |
Console | java.io.Console | 支持无回显密码 | 真终端交互 | IDE 中可能为 null |
三、Scanner:最常用也最易踩坑的方案
1. 基本用法
import java.util.*;public class ScannerDemo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.print("请输入 姓名 年龄 身高:");String name = sc.next();int age = sc.nextInt();double height = sc.nextDouble();System.out.println("name=" + name + ", age=" + age + ", height=" + height);}
}
-
默认分隔符:空白字符。
-
可自定义分隔符:sc.useDelimiter(“,”)。
-
读整行:sc.nextLine()。
-
读单字符:sc.next().charAt(0)。
2. 健壮性输入
while (true) {System.out.print("请输入一个整数:");if (sc.hasNextInt()) {int n = sc.nextInt();sc.nextLine(); // 吃掉换行break;} else {System.out.println("输入错误,请重试!");sc.nextLine(); // 丢弃错误输入}
}
3. 常见坑
-
换行问题: nextInt() 后跟 nextLine() → 会读到空串。
-
Locale 影响小数点: 用 sc.useLocale(Locale.US) 固定为 .。
-
不要关闭 Scanner: 否则会关掉底层 System.in。
四、BufferedReader + InputStreamReader:高效可控的选择
1. 逐行读取
BufferedReader br = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)
);
String line;
while ((line = br.readLine()) != null) {System.out.println("读到:" + line);
}
-
readLine():返回整行(不含换行符);EOF 返回 null。
-
显式指定编码(如 UTF-8)以避免乱码。
2. 快读模板(竞赛常用)
static class FastScanner {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StringTokenizer st;String next() throws IOException {while (st == null || !st.hasMoreTokens()) {String line = br.readLine();if (line == null) return null;st = new StringTokenizer(line);}return st.nextToken();}int nextInt() throws IOException { return Integer.parseInt(next()); }
}
特点:比 Scanner 更快,适合大数据量。
五、Console:真正的控制台交互
Console cons = System.console();
if (cons == null) {System.err.println("No console available");return;
}
String user = cons.readLine("用户名: ");
char[] pwd = cons.readPassword("密码: ");
-
可隐藏密码输入(不回显)。
-
在 IDE 中常返回 null,需在终端运行 java 命令。
六、编码、Locale 与行结束符
-
编码: Scanner 默认平台编码;推荐 BufferedReader + UTF-8。
-
Locale: Scanner 解析小数受 Locale 影响;统一用 Locale.US。
-
行结束符: readLine() 和 Scanner 已屏蔽平台差异(\r\n vs \n)。
七、总结
-
Scanner: 最方便,适合日常。
-
BufferedReader: 高效,适合性能敏感场景。
-
Console: 增强交互,适合终端工具。