news 2026/1/23 20:08:08

Scanner类常用方法完整示例讲解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Scanner类常用方法完整示例讲解

一文吃透Java中Scanner类的用法:从入门到实战避坑

你有没有遇到过这样的情况?写了个简单的控制台程序,用户输入一个数字后,接下来要读取一句话,结果nextLine()居然直接“跳过了”!或者在算法题里反复提交失败,只因为多了一个换行符没处理好。

别急,这背后大概率是Scanner的使用姿势不对。作为 Java 初学者接触最早的输入工具之一,Scanner看似简单,实则暗藏玄机。今天我们就来彻底搞懂它——不只是怎么用,更要明白为什么这么用


为什么是 Scanner?

在 Java 中,想要从键盘获取用户输入,最直观的方式就是Scanner。它位于java.util.Scanner包下,设计初衷就是为了简化文本解析过程。尤其对于刚学编程的同学来说,比起复杂的流操作,几行代码就能读整数、读字符串,简直不要太友好。

更重要的是,在 LeetCode、牛客网、蓝桥杯等主流平台中,标准输入往往通过System.in提供,而Scanner正好能无缝对接。可以说,掌握它的正确用法,是你刷题和做小项目的“基本功”。

但问题是:很多人只记住了方法名,却忽略了它们之间的行为差异,最终掉进了“输入残留”的经典陷阱。

我们先来看一个最常见的问题场景:

Scanner sc = new Scanner(System.in); System.out.print("请输入年龄: "); int age = sc.nextInt(); System.out.print("请输入姓名: "); String name = sc.nextLine(); // 这里竟然读不到!

运行时你会发现,“请输入姓名”刚打印出来,程序就仿佛自动跳过了输入,直接往下走了。这是怎么回事?

答案就在nextInt()nextLine()的工作机制不同上。


核心机制:Scanner 是如何工作的?

Scanner并不是逐字节读取输入,而是把整个输入当作一个“流”,内部维护着一个缓冲区,并按“token”(令牌)进行拆分。默认情况下,它的分隔符是任意空白字符(空格、制表符、换行符),也就是说:

除了nextLine(),所有nextXxx()方法都会自动跳过前导空白,然后读取直到下一个空白之前的内容。

关键点来了:
-nextInt()会读取数字部分,但不会消费后面的换行符
- 而nextLine()的任务是从当前位置一直读到下一个换行符为止
- 所以当你调用完nextInt()后立刻调用nextLine(),后者其实是在“吃掉”那个残留的换行符,于是返回了一个空字符串。

这就解释了上面那个“跳过输入”的现象。

如何解决?加一行清理即可!

int age = sc.nextInt(); sc.nextLine(); // 手动清空缓冲区中的换行符 String name = sc.nextLine(); // 现在可以正常输入了

记住这个模式:只要你在nextXxx()之后要用nextLine(),就必须先手动调用一次nextLine()来清除残余。


常用方法详解与最佳实践

下面我们逐一拆解Scanner的核心 API,结合实际场景讲清楚每个方法该怎么用、什么时候用、有哪些坑。

nextInt()/nextDouble():读取基本类型

这两个是最常用的数值输入方法,适用于读取整数或浮点数。

System.out.print("请输入分数: "); double score = scanner.nextDouble();

优点
- 自动完成字符串转数字;
- 如果输入非法(比如输入“abc”),会抛出InputMismatchException

建议搭配hasNextXxx()使用以增强健壮性

while (!scanner.hasNextDouble()) { System.out.println("请输入有效的数字!"); scanner.next(); // 清除非法输入 } double score = scanner.nextDouble();

这里的关键在于:hasNextDouble()只判断不消费,如果验证失败,需要用next()把错误内容“扔掉”,否则会陷入死循环。


next()vsnextLine():一字之差,天壤之别

方法行为说明
next()读取下一个由空白分隔的单词,不能包含空格
nextLine()读取当前行剩余全部内容,包括空格,直到遇到换行

举个例子:

输入:张三 今年 20 岁

  • scanner.next()→ 得到"张三"
  • 再次调用 →"今年"
  • 再调用 →"20"

但如果用nextLine(),在同一行后续调用就会得到" 今年 20 岁"(注意开头有空格)。

所以如果你想读一句话,比如“我喜欢编程”,里面有空格,那就必须用nextLine()

常见误区:以为next()能读带空格的名字 —— 实际上只能读第一个词。

✅ 正确做法:

System.out.print("请输入完整姓名: "); String fullName = scanner.nextLine();

hasNextXxx():让输入更安全

在不知道用户要输多少数据的情况下,hasNextInt()这类方法非常有用。典型应用场景:OJ系统接收多组测试数据。

System.out.println("持续输入整数(非数字结束):"); while (scanner.hasNextInt()) { int n = scanner.nextInt(); System.out.println("收到: " + n); } // 当输入 abc 时,循环自然退出

这种方式避免了硬编码输入次数,也防止因类型错误导致程序崩溃。


useDelimiter(String pattern):自定义分割规则

默认是按空白拆分,但如果你处理的是 CSV 文件或特定格式的数据,就需要改分隔符。

例如读取逗号分隔的水果列表:

String data = "苹果,香蕉,橘子"; Scanner scanner = new Scanner(data); scanner.useDelimiter(","); while (scanner.hasNext()) { System.out.println("水果: " + scanner.next()); } scanner.close();

输出:

水果: 苹果 水果: 香蕉 水果: 橘子

你甚至可以用正则表达式设置复杂分隔符,比如.useDelimiter("[,;\\s]+")表示逗号、分号或空白都可作为分隔。


close():别忘了关资源

虽然从System.in创建的Scanner关不关影响不大,但在读文件时,必须关闭,否则可能造成资源泄漏。

推荐写法(Java 7+):

try (Scanner scanner = new Scanner(new File("scores.txt"))) { while (scanner.hasNextLine()) { System.out.println(scanner.nextLine()); } } catch (FileNotFoundException e) { System.err.println("文件未找到"); }

这就是所谓的try-with-resources语法,自动帮你调用close(),代码更简洁、更安全。


实战案例:学生信息录入系统

我们来写一个完整的交互式程序,综合运用上述技巧,实现一个带输入校验的学生信息录入系统。

import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class StudentRecorder { public static void main(String[] args) { List<Student> students = new ArrayList<>(); Scanner scanner = new Scanner(System.in); System.out.println("=== 学生信息录入系统 ==="); System.out.println("输入 'quit' 结束录入"); while (true) { System.out.print("\n姓名: "); String name = scanner.nextLine(); if ("quit".equalsIgnoreCase(name)) break; // 安全读取年龄 System.out.print("年龄: "); while (!scanner.hasNextInt()) { System.out.println("请输入有效数字!"); scanner.next(); // 清除非法输入 } int age = scanner.nextInt(); scanner.nextLine(); // 清除换行 // 安全读取成绩 System.out.print("成绩: "); while (!scanner.hasNextDouble()) { System.out.println("请输入有效分数!"); scanner.next(); } double score = scanner.nextDouble(); scanner.nextLine(); // 清除换行 students.add(new Student(name, age, score)); System.out.println("【已保存】" + name); } System.out.println("\n✅ 录入完成,共 " + students.size() + " 人:"); students.forEach(System.out::println); scanner.close(); } } class Student { private final String name; private final int age; private final double score; public Student(String name, int age, double score) { this.name = name; this.age = age; this.score = score; } @Override public String toString() { return String.format("👤 %s | 年龄: %d | 成绩: %.1f", name, age, score); } }

这个程序解决了几个关键问题:
- 输入中断保护:用hasNextXxx()检查类型合法性;
- 错误恢复:非法输入不会导致程序崩溃;
- 缓冲清理:每次读完基本类型后立即清理换行;
- 用户体验:提示清晰,支持中途退出;
- 资源管理:最后调用了close()


性能提醒:Scanner 不适合大数据量场景

尽管Scanner使用方便,但它毕竟是封装层较厚的工具类,底层做了大量正则匹配和异常处理,性能远不如原始流。

如果你在处理百万级数据输入(如大型 OJ 题目),建议改用:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = br.readLine(); int n = Integer.parseInt(line);

或者配合StringTokenizer提高效率:

StringTokenizer st = new StringTokenizer(br.readLine()); while (st.hasMoreTokens()) { int num = Integer.parseInt(st.nextToken()); }

这类组合虽然代码稍长,但速度更快,内存占用更低,是竞赛选手的首选。


最佳实践总结

场景推荐做法
读整数/浮点数优先使用nextInt()/nextDouble()
读带空格字符串必须用nextLine()
混合调用前后nextXxx()后接nextLine(),记得加一次nextLine()清缓冲
输入验证使用hasNextXxx()+next()清错
特殊格式数据设置useDelimiter()
文件读取务必使用 try-with-resources
高性能需求改用BufferedReader + parseInt

如果你正在学习 Java,或是准备参加算法竞赛,不妨把这篇文章收藏起来。下次再遇到“输入莫名其妙跳过”的问题,你就知道该去哪找答案了。

掌握Scanner不只是学会几个方法,更是理解输入流、缓冲机制和类型转换的第一步。它是通向更高级 I/O 模型的起点,也是写出健壮交互程序的基础能力。

你现在对Scanner还有什么疑惑吗?欢迎在评论区留言讨论!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/23 13:05:06

基于GLM-TTS的语音博客平台设计:文字一键转播客节目

基于GLM-TTS的语音博客平台设计&#xff1a;文字一键转播客节目 在移动互联网时代&#xff0c;人们越来越习惯于“耳朵阅读”——通勤、健身、做家务时收听优质内容已成为主流。文字创作者们也敏锐地意识到这一点&#xff0c;纷纷尝试将文章转化为播客。但专业录音成本高、周期…

作者头像 李华
网站建设 2026/1/22 6:51:55

dify工作流集成设想:将GLM-TTS嵌入低代码语音生成系统

将 GLM-TTS 深度集成至 Dify&#xff1a;构建低代码语音生成系统的实践路径 在智能内容生产加速演进的今天&#xff0c;个性化语音合成正从“技术实验”走向“业务刚需”。无论是企业希望用高管声音播报年报摘要&#xff0c;还是教育机构需要复刻教师语调批量生成课程音频&…

作者头像 李华
网站建设 2026/1/22 9:40:00

GLM-TTS能否支持股票行情播报?实时数据语音更新

GLM-TTS能否支持股票行情播报&#xff1f;实时数据语音更新 在金融交易大厅的屏幕上&#xff0c;数字每秒跳动&#xff1b;而在智能音箱里&#xff0c;一声清亮的女声正缓缓读出&#xff1a;“宁德时代涨幅6.3%&#xff0c;成交额突破20亿元。”——这不是人工主播&#xff0c;…

作者头像 李华
网站建设 2026/1/21 7:07:13

3.5 线性变换的度量

1.线性变换的度量 2.改变基向量1.线性变换的度量 1).任何一个线性变换都可用矩阵表示, 如果给定一个向量空间V中的向量v, 如何找到向量空间W中的T(v); 其中V的基向量:v1, v2 ... vna.将v写为基向量线性组合的形式v c1v1 c2v2 ... cnvnb.T(v) T(c1v1 c2v2 ... cnvn) -&g…

作者头像 李华
网站建设 2026/1/22 18:06:41

被英伟达30亿美金盯上的AI21 Labs:凭什么200人团队值天价?

被英伟达30亿美金盯上的AI21 Labs&#xff1a;凭什么200人团队值天价&#xff1f; 近期AI圈最大瓜&#xff0c;莫过于英伟达拟砸20-30亿美金收购以色列AI初创公司AI21 Labs——要知道这家公司2023年估值才14亿&#xff0c;短短两年报价近乎翻倍&#xff0c;按200人团队规模算&a…

作者头像 李华