
学 Java 时你写的第一行代码大概率是这个System.out.println(Hello, World!);这就是 Java 的输出——让程序把内容显示出来。反过来让程序听用户说话就需要输入。这篇文章把这两件事讲清楚。一、输出程序能做的最基本的事就是把结果告诉用户。Java 控制台输出有三个常用方法适合不同的场景。1.1 三种输出方式print— 输出内容不换行System.out.print(你好);System.out.print(世界);// 输出你好世界println— 输出内容末尾自动换行print line 的缩写System.out.println(你好);System.out.println(世界);// 输出// 你好// 世界printf— 格式化输出适合需要对齐或控制小数位数的场景Stringname小明;intage18;doublescore92.5;System.out.printf(姓名%s年龄%d成绩%.1f%n,name,age,score);// 输出姓名小明年龄18成绩92.5常用格式占位符占位符含义示例%s字符串小明%d整数18%f浮点数默认 6 位小数92.500000%.2f浮点数保留 2 位小数92.50%n换行跨平台—1.2 转义字符三种输出方法解决了输出什么的问题但有些字符本身没法直接写进字符串——比如换行、缩进或者双引号。这时就需要转义字符在反斜杠\后面跟一个特定字母代表那个字符// \n 换行System.out.println(第一行\n第二行);// 输出// 第一行// 第二行// \t 制表符Tab 键的效果System.out.println(姓名\t成绩);System.out.println(小明\t92);System.out.println(小红\t88);// 输出// 姓名 成绩// 小明 92// 小红 88// \ 在字符串里输出双引号System.out.println(他说\今天天气真好\);// 输出他说今天天气真好1.3 综合例子打印购物小票把三种输出方式和转义字符放在一起用效果会更直观。下面用printf的对齐功能打一张整齐的购物小票publicclassReceipt{publicstaticvoidmain(String[]args){System.out.println( 购物小票 );System.out.printf(%-10s %5s %8s%n,商品,数量,价格);System.out.println(------------------------------);System.out.printf(%-10s %5d %8.2f%n,苹果,3,15.00);System.out.printf(%-10s %5d %8.2f%n,牛奶,2,12.50);System.out.printf(%-10s %5d %8.2f%n,面包,1,8.00);System.out.println(------------------------------);System.out.printf(合计%22.2f 元%n,35.50);System.out.println();}}输出 购物小票 商品 数量 价格 ------------------------------ 苹果 3 15.00 牛奶 2 12.50 面包 1 8.00 ------------------------------ 合计 35.50 元 %-10s中的-表示左对齐10表示占 10 个字符宽度不足的用空格补齐。二、输入输出解决了程序说话的问题。但一个有用的程序通常需要根据用户的情况给出不同结果这就需要输入——让用户把数据喂给程序。2.1 Scanner 基础Java 读取用户输入用Scanner类它在java.util包里用之前要先导入importjava.util.Scanner;publicclassGreeting{publicstaticvoidmain(String[]args){ScannerscannernewScanner(System.in);System.out.print(请输入你的名字);Stringnamescanner.next();// 读取一个词System.out.println(你好name);scanner.close();// 用完记得关闭}}运行效果请输入你的名字小明 你好小明2.2 四种读取方法逐一搞清楚Scanner提供了好几个读取方法名字长得很像容易混。我们一个个拆开来看把它们彻底区分清楚。nextInt()— 读取整数用户输入一个整数按回车程序把这个数字存起来ScannerscannernewScanner(System.in);System.out.print(请输入你的年龄);intagescanner.nextInt();System.out.println(你的年龄是age);请输入你的年龄18 你的年龄是18如果用户输入18.5或者abc程序会报错——nextInt()只认整数。nextDouble()— 读取小数和nextInt()一样只是换成了小数ScannerscannernewScanner(System.in);System.out.print(请输入身高米);doubleheightscanner.nextDouble();System.out.printf(你的身高是 %.2f 米%n,height);请输入身高米1.75 你的身高是 1.75 米整数也能用nextDouble()读输入2会得到2.0。next()— 读取下一段连续非空白内容next()、nextInt()、nextDouble()背后是同一套扫描机制分两步走跳过缓冲区开头所有的空白字符空格、Tab、换行读取直到遇到下一个空白字符为止的那段字符序列next()在第二步后直接把这段内容作为字符串返回nextInt()和nextDouble()则多做一步类型转换类似Integer.parseInt/Double.parseDouble如果转换失败会抛出异常。所以这三个方法不是函数重载意义上的各司其职而是同一条扫描路径走到底最后用不同方式处理结果ScannerscannernewScanner(System.in);// 以下三行各自单独运行输入如注释所示intascanner.nextInt();// 输入 42 → 扫描得到 42解析成整数 42doublebscanner.nextDouble();// 输入 3.14 → 扫描得到 3.14解析成小数 3.14Stringcscanner.next();// 输入 hello → 扫描得到 hello直接返回字符串输入错误类型时会抛异常nextInt()遇到abc会报InputMismatchException因为abc无法被解析成整数。next()遇到空白字符就停所以输入里如果有空格它只拿空格前面那段ScannerscannernewScanner(System.in);System.out.print(请输入);Stringwordscanner.next();System.out.println(读到[word]);输入hello world结果是请输入hello world 读到[hello]world没有丢失它还留在缓冲区里等下一次读取。所以如果你连续调用两次next()Stringfirstscanner.next();Stringsecondscanner.next();System.out.println(first / second);输入hello world会得到hello / worldnextLine()— 读取整行nextLine()读到换行符为止也就是用户按下回车键之前输入的所有内容包括空格ScannerscannernewScanner(System.in);System.out.print(请输入你的地址);Stringaddressscanner.nextLine();System.out.println(地址[address]);请输入你的地址北京市 朝阳区 某某街道 地址[北京市 朝阳区 某某街道]空格原样保留整行都读进来了。四种方法对比方法读到什么为止适合读什么nextInt()空白字符空格/Tab/换行整数nextDouble()空白字符小数next()空白字符单个单词/无空格的字符串nextLine()换行符回车带空格的一整行文字空白字符指空格、Tab、换行符这三种。nextInt/nextDouble/next遇到任意一种都会停nextLine只在换行时停。2.3next和nextLine的区别——初学者必踩的坑上面说到next()遇到空白字符就停nextLine()读到换行符为止。两者单独用都没问题但混在一起用时有个陷阱几乎每个初学者都会踩一次。next()遇到空格就停只读空格前的内容ScannerscannernewScanner(System.in);System.out.print(输入);Stringsscanner.next();System.out.println(读到s);输入hello world 读到hello ← 只读了 helloworld 留在缓冲区nextLine()读整行直到回车ScannerscannernewScanner(System.in);System.out.print(输入);Stringsscanner.nextLine();System.out.println(读到s);输入hello world 读到hello world ← 整行都读进来了陷阱nextInt之后用nextLine问题出在nextInt()读完数字之后。用户按回车时缓冲区里会留下一个\n而nextInt()并不消耗它——它只拿走了数字本身。紧接着调用nextLine()时它立刻读到这个残留的\n误以为用户输入了一行空内容就结束了// 错误示范ScannerscannernewScanner(System.in);System.out.print(请输入年龄);intagescanner.nextInt();System.out.print(请输入地址);Stringaddressscanner.nextLine();// ⚠️ 这里读到的是空字符串System.out.println(年龄age);System.out.println(地址address);解决办法是在nextInt()后面加一行scanner.nextLine()把那个残留的回车消耗掉再正式读取地址// 正确写法ScannerscannernewScanner(System.in);System.out.print(请输入年龄);intagescanner.nextInt();scanner.nextLine();// 消耗残留的回车符System.out.print(请输入地址);Stringaddressscanner.nextLine();// 现在能正常读取了System.out.println(年龄age);System.out.println(地址address);请输入年龄18 请输入地址北京市朝阳区 年龄18 地址北京市朝阳区nextDouble()之后接nextLine()也有同样的问题处理方式相同。2.4 多组输入实际程序里往往需要让用户输入不止一组数据。有两种常见做法。方式一事先知道要输入几组——用for循环先问用户有多少条数据再循环读取importjava.util.Scanner;publicclassMultiInput{publicstaticvoidmain(String[]args){ScannerscannernewScanner(System.in);System.out.print(请输入学生人数);intnscanner.nextInt();scanner.nextLine();// 消耗残留回车for(inti1;in;i){System.out.print(请输入第 i 位学生的姓名);Stringnamescanner.nextLine();System.out.print(请输入 name 的成绩);intscorescanner.nextInt();scanner.nextLine();// 消耗残留回车System.out.printf(已记录%s — %d 分%n,name,score);}scanner.close();}}运行效果请输入学生人数3 请输入第 1 位学生的姓名小明 请输入小明的成绩90 已记录小明 — 90 分 请输入第 2 位学生的姓名小红 请输入小红的成绩85 已记录小红 — 85 分 请输入第 3 位学生的姓名小刚 请输入小刚的成绩78 已记录小刚 — 78 分方式二不知道要输入几组——用while循环输入特定值退出让用户输入数据直到输入约定好的结束信号为止。这种模式叫哨兵值sentinel valueimportjava.util.Scanner;publicclassSentinelInput{publicstaticvoidmain(String[]args){ScannerscannernewScanner(System.in);inttotal0;intcount0;System.out.println(请依次输入成绩输入 -1 结束);intscorescanner.nextInt();while(score!-1){totalscore;count;scorescanner.nextInt();}if(count0){System.out.printf(共 %d 个成绩平均分%.1f%n,count,(double)total/count);}else{System.out.println(没有输入任何成绩。);}scanner.close();}}运行效果请依次输入成绩输入 -1 结束 90 85 78 92 -1 共 4 个成绩平均分86.3哨兵值的选取原则选一个在正常业务中不可能出现的值。成绩用-1年龄可以用0字符串输入常用quit或exit。方式三读到文件末尾——hasNextXxx()如果输入来自文件或管道而不是键盘用hasNext()/hasNextInt()判断还有没有数据importjava.util.Scanner;publicclassHasNextInput{publicstaticvoidmain(String[]args){ScannerscannernewScanner(System.in);intsum0;intcount0;while(scanner.hasNextInt()){// 有整数就继续读sumscanner.nextInt();count;}System.out.printf(共 %d 个数总和%d%n,count,sum);scanner.close();}}在竞赛题和算法练习中这种写法很常见——测试数据从文件重定向进来程序读完所有数据后自然退出。2.5 综合例子成绩查询系统importjava.util.Scanner;publicclassScoreQuery{publicstaticvoidmain(String[]args){ScannerscannernewScanner(System.in);System.out.println( 成绩查询系统 );System.out.print(请输入学生姓名);Stringnamescanner.nextLine();System.out.print(请输入语文成绩);intchinesescanner.nextInt();System.out.print(请输入数学成绩);intmathscanner.nextInt();System.out.print(请输入英语成绩);intenglishscanner.nextInt();doubleaverage(chinesemathenglish)/3.0;System.out.println(\n 成绩单 );System.out.printf(姓名%s%n,name);System.out.printf(语文%d 分%n,chinese);System.out.printf(数学%d 分%n,math);System.out.printf(英语%d 分%n,english);System.out.printf(平均%.1f 分%n,average);scanner.close();}}运行效果 成绩查询系统 请输入学生姓名小红 请输入语文成绩90 请输入数学成绩85 请输入英语成绩92 成绩单 姓名小红 语文90 分 数学85 分 英语92 分 平均89.0 分总结操作用法不换行输出System.out.print(...)换行输出System.out.println(...)格式化输出System.out.printf(格式, 参数...)读取单词scanner.next()读取整行scanner.nextLine()读取整数scanner.nextInt()读取小数scanner.nextDouble()记住一个关键点nextInt/nextDouble之后如果要用nextLine先加一行scanner.nextLine()清空缓冲区。这个坑几乎每个 Java 初学者都会踩一次。