第4章 输入、输出和命令行交互
前几章的代码大多把数据写死在程序里:
java
int age = 18;
String name = "小林";
这样能练语法,但不是真正的交互程序。真实程序通常需要从外部接收数据:用户输入姓名、输入成绩、输入菜单选项,程序再根据输入做处理。
这一章要解决三个问题:
- Java 怎么把内容输出给用户看。
- Java 怎么从键盘读取用户输入。
- 输入不合法时程序为什么会崩,以及怎么防。
学完本章后,你就能写简单的命令行交互程序。
一、输出:println 和 print
最常用输出:
java
System.out.println("Hello Java");
println 会输出内容,并换行。
java
System.out.println("第一行");
System.out.println("第二行");
输出:
text
第一行
第二行
print 不换行:
java
System.out.print("姓名:");
System.out.print("小林");
输出:
text
姓名:小林
它们的区别:
| 方法 | 是否换行 | 常见用途 |
|---|---|---|
println |
换行 | 输出结果、日志、提示 |
print |
不换行 | 输出输入提示,如 请输入姓名: |
比如:
java
System.out.print("请输入姓名:");
用户会在同一行输入。
二、格式化输出:让内容更清楚
字符串拼接可以输出:
java
String name = "小林";
int age = 18;
System.out.println("姓名:" + name + ",年龄:" + age);
也可以用 printf:
java
System.out.printf("姓名:%s,年龄:%d%n", name, age);
常见占位符:
| 占位符 | 含义 |
|---|---|
%s |
字符串 |
%d |
整数 |
%f |
小数 |
%.2f |
保留两位小数 |
%n |
换行 |
示例:
java
double price = 19.9;
System.out.printf("价格:%.2f元%n", price);
输出:
text
价格:19.90元
入门阶段你可以先主要用字符串拼接,遇到金额、平均分这类需要控制小数位的,再用 printf。
三、Scanner:从键盘读取输入
Java 读取命令行输入常用 Scanner。
java
import java.util.Scanner;
public class InputDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入姓名:");
String name = scanner.nextLine();
System.out.println("你好," + name);
}
}
拆开看:
java
import java.util.Scanner;
表示导入 Scanner 类。Java 标准库里有很多类,用到时要导入。
java
Scanner scanner = new Scanner(System.in);
创建一个 Scanner,让它从标准输入 System.in 读取数据。标准输入通常就是键盘。
java
String name = scanner.nextLine();
读取用户输入的一整行文本。
四、读取不同类型的数据
读取字符串:
java
String name = scanner.nextLine();
读取整数:
java
int age = scanner.nextInt();
读取小数:
java
double height = scanner.nextDouble();
完整示例:
java
import java.util.Scanner;
public class ProfileInput {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入姓名:");
String name = scanner.nextLine();
System.out.print("请输入年龄:");
int age = scanner.nextInt();
System.out.print("请输入身高:");
double height = scanner.nextDouble();
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
System.out.println("身高:" + height);
}
}
运行后,程序会停下来等待用户输入。这和前面写死变量不一样。
五、nextLine 和 nextInt 混用的坑
看这段代码:
java
Scanner scanner = new Scanner(System.in);
System.out.print("请输入年龄:");
int age = scanner.nextInt();
System.out.print("请输入姓名:");
String name = scanner.nextLine();
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
你可能发现:输入年龄后,姓名还没来得及输入,程序就结束了。
原因是:nextInt() 读取数字,但不会吃掉最后的换行符。后面的 nextLine() 读到了那个残留换行,于是得到空字符串。
解决方式:在 nextInt() 后面补一次 nextLine() 吃掉换行。
java
System.out.print("请输入年龄:");
int age = scanner.nextInt();
scanner.nextLine();
System.out.print("请输入姓名:");
String name = scanner.nextLine();
另一种方式是所有输入都用 nextLine() 读取字符串,再自己转换:
java
System.out.print("请输入年龄:");
String ageText = scanner.nextLine();
int age = Integer.parseInt(ageText);
这种方式更统一,也更适合后面做错误处理。
六、输入不合法会怎样
如果代码是:
java
int age = scanner.nextInt();
用户输入:
text
abc
程序会抛出异常:
text
InputMismatchException
因为 abc 不能当作整数读取。
如果使用:
java
String ageText = scanner.nextLine();
int age = Integer.parseInt(ageText);
用户输入 abc,会出现:
text
NumberFormatException
两种本质一样:输入和程序期待的类型不匹配。
第一阶段我们先用简单方式处理:先判断字符串是否像数字。
java
public static boolean isInteger(String text) {
if (text == null || text.isEmpty()) {
return false;
}
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if (ch < '0' || ch > '9') {
return false;
}
}
return true;
}
使用:
java
System.out.print("请输入年龄:");
String ageText = scanner.nextLine();
if (!isInteger(ageText)) {
System.out.println("年龄必须是整数");
return;
}
int age = Integer.parseInt(ageText);
这里我们还没系统讲方法,但你可以先看到:把校验逻辑拆成方法,主流程会更清楚。
七、命令行参数和 Scanner 的区别
上一章讲过 String[] args:
bash
java ArgsDemo Tom 18
参数在程序启动时就给好。
Scanner 是程序运行过程中再让用户输入。
对比:
| 方式 | 数据什么时候进入程序 | 适合场景 |
|---|---|---|
String[] args |
启动程序时 | 脚本参数、配置项、一次性命令 |
Scanner |
程序运行中 | 菜单、交互、用户逐步输入 |
命令行参数示例:
java
public class ArgsProfile {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("用法:java ArgsProfile <姓名> <年龄>");
return;
}
String name = args[0];
int age = Integer.parseInt(args[1]);
System.out.println(name + ":" + age);
}
}
Scanner 示例:
java
Scanner scanner = new Scanner(System.in);
System.out.print("请输入姓名:");
String name = scanner.nextLine();
第一阶段的交互项目主要用 Scanner。
八、做一个注册信息输入程序
需求:
- 输入姓名。
- 输入年龄。
- 输入手机号。
- 判断姓名不能为空。
- 判断年龄是否是整数。
- 判断手机号长度是否为 11。
- 输出注册结果。
代码:
java
import java.util.Scanner;
public class RegisterInputDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入姓名:");
String name = scanner.nextLine();
if (name == null || name.isEmpty()) {
System.out.println("姓名不能为空");
return;
}
System.out.print("请输入年龄:");
String ageText = scanner.nextLine();
if (!isInteger(ageText)) {
System.out.println("年龄必须是整数");
return;
}
int age = Integer.parseInt(ageText);
if (age < 18) {
System.out.println("未满18岁,不能注册");
return;
}
System.out.print("请输入手机号:");
String phone = scanner.nextLine();
if (phone == null || phone.length() != 11) {
System.out.println("手机号必须是11位");
return;
}
System.out.println("注册成功");
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
System.out.println("手机号:" + phone);
}
public static boolean isInteger(String text) {
if (text == null || text.isEmpty()) {
return false;
}
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if (ch < '0' || ch > '9') {
return false;
}
}
return true;
}
}
这段代码已经有一点真实程序的样子了:
- 数据来自用户输入。
- 输入后先校验。
- 不合法就提前 return。
- 合法才继续后续流程。
- 把整数判断拆成方法。
九、为什么要先校验再使用
很多新手会直接:
java
int age = Integer.parseInt(scanner.nextLine());
用户输入正确时没问题。但用户输入 abc,程序直接崩。
更稳的流程:
text
读取原始输入
-> 校验
-> 转换
-> 使用
代码:
java
String ageText = scanner.nextLine();
if (!isInteger(ageText)) {
System.out.println("年龄格式错误");
return;
}
int age = Integer.parseInt(ageText);
这个思维非常重要。以后处理网络、文件、数据库也是一样:外部输入永远不要默认可信。
十、常见错误
1. 忘记导入 Scanner
java
Scanner scanner = new Scanner(System.in);
如果没有:
java
import java.util.Scanner;
会编译失败。
2. nextInt 和 nextLine 混用
读取数字后又读取整行,可能读到残留换行。解决方式是补 scanner.nextLine(),或者统一用 nextLine()。
3. 输入类型不匹配
用户输入 abc,但程序按 int 读取,会异常。
4. 没校验空字符串
java
String name = scanner.nextLine();
用户直接回车,name 是空字符串,不是 null。要用:
java
name.isEmpty()
5. 把用户输入当成永远正确
真实程序不能假设用户一定按提示输入。越靠近外部输入,越要防御。
十一、本章练习
-
写一个程序,输入姓名和城市,输出一句自我介绍。
-
写一个程序,输入两个整数,输出它们的和。
-
写一个程序,输入身高和体重,计算 BMI。
-
写一个程序,输入年龄,判断是否成年。要求年龄不是整数时提示错误。
-
修改注册程序:手机号必须以
1开头。
十二、本章总结
本章你需要掌握:
println输出并换行。print输出不换行。printf可以格式化输出。Scanner可以读取用户输入。nextLine读取整行。nextInt、nextDouble读取指定类型,但要注意输入不匹配。nextInt和nextLine混用会有换行残留问题。- 命令行参数适合启动时传入,Scanner 适合运行中交互。
- 外部输入必须先校验再使用。
学完这一章,程序已经可以和用户互动了。下一章会讲条件判断,把输入数据转成不同的业务分支。