next()读到首个空白符即停,不能读空格;nextLine()读至换行符为止,可读整行含空格;混用nextInt()与nextLine()会因换行符残留导致nextLine()返回空字符串。

Scanner 读取字符串时 next() 和 nextLine() 的区别
用 Scanner 读取用户输入,最常踩的坑是混用 next() 和 nextLine() 导致跳过输入。比如先调 nextInt() 读数字,再调 nextLine() 想读下一行文本,结果直接返回空字符串——因为 nextInt() 不消费换行符,nextLine() 立刻读到那个残留的 \n 就结束了。
实际建议:
- 统一用
nextLine()读所有输入,后续再用Integer.parseInt()、Double.parseDouble()转类型,避免缓冲区残留问题 - 如果非要用
next()类方法(如nextDouble()),记得在之后加一句scanner.nextLine()吃掉换行符 -
next()只读到第一个空白符(空格/制表/换行)就停;nextLine()读到换行符为止,能拿到整行包括中间空格
处理输入异常:NoSuchElementException 和 InputMismatchException
用户不按预期输入时,Scanner 会抛异常:NoSuchElementException(流已结束,比如用户直接 Ctrl+D 或输入被重定向为空)或 InputMismatchException(比如调 nextInt() 却输了个字母)。
不能靠 catch 异常来“控制流程”,得提前校验:
- 用
hasNextInt()、hasNextDouble()、hasNextLine()判断再读,而不是硬读再 try-catch - 如果用户输错,要清空当前 token(用
next()吃掉非法输入),否则下次hasNextXxx()还会返回 false,陷入死循环 - 示例:想读一个合法整数,但用户输 "abc",应调一次
scanner.next()清掉它,再提示重新输入
关闭 Scanner 是否必要?什么时候关?
对 System.in 创建的 Scanner,**不要调 close()**。一旦关闭,System.in 就不可再用,后续任何其他读取操作(包括另一个 Scanner)都会抛 IllegalStateException。
只有以下情况才该关:
- Scanner 包装的是文件流(
new Scanner(new FileInputStream("a.txt"))),用完必须关,否则文件句柄泄露 - Scanner 包装的是字符串(
new Scanner("123 abc")),关不关都行,但关了更明确 - 用 try-with-resources 时,仅当资源本身可安全关闭(如文件)才适用;
System.in不在此列
中文输入乱码怎么办?
在 Windows 命令行(cmd)或某些 IDE 终端里,Scanner 默认用平台编码读输入,而中文常被当成 GBK,但 Java 字符串内部是 UTF-16,导致乱码。根本原因是 System.in 的字节流没指定正确字符集。
解决方式只有一条路:
- 别用默认构造函数
new Scanner(System.in),改用带Charset的构造:new Scanner(System.in, "UTF-8")(推荐)或new Scanner(System.in, "GBK")(仅限 Windows cmd 确认是 GBK 时) - 注意:IDE 内置终端(如 IntelliJ 的 Terminal)通常设为 UTF-8,用
"UTF-8"更通用;Windows cmd 默认是 GBK,但可通过chcp 65001切到 UTF-8,然后统一用"UTF-8" - 这个参数只影响 Scanner 解码字节流的过程,不影响后续 String 对象——String 始终是 UTF-16,无需额外处理
真正麻烦的是环境编码不一致:同一段代码,在 macOS/Linux 终端跑正常,在 Windows cmd 里乱码,或者在 IDE 里正常,打包成 jar 后命令行运行又乱码。这种时候,别猜,先用 java -Dfile.encoding=UTF-8 启动,再确认终端实际编码,最后固定 Scanner 的 charset 参数。










