1. 为什么从输入输出开始学Java?
刚接触Java的新手常会问:为什么第一章就要学输入输出?这就像学开车先学踩油门和刹车——没有输入输出的程序就像没有方向盘的汽车,再好的引擎也跑不起来。Java的System.out.println()可能是你职业生涯中写的最多的一行代码,而Scanner类则是与用户对话的起点。
我在带新人时发现,90%的初学者第一个bug都出在输入输出处理上。有个实习生曾花三天时间调试一段"看似正确"的代码,最后发现只是忘了import java.util.Scanner。这个惨痛教训让我决定把输入输出作为Java入门的第一块基石。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础输出:你的第一行Java代码
2.1 System.out.println()解剖
java复制public class HelloWorld {
public static void main(String[] args) {
System.out.println("你好,Java世界!");
}
}
这行经典代码藏着几个关键知识点:
- System是java.lang包下的最终类(自动导入)
- out是System类的静态PrintStream对象
- println()方法会自动追加换行符
注意:早期教材常用print()而非println(),现代IDE生成的模板默认使用后者,因为更符合日志输出需求
2.2 格式化输出技巧
当需要混合输出文本和变量时,推荐使用printf():
java复制int age = 25;
System.out.printf("我今年%d岁,存款%.2f元\n", age, 5000.0);
// 输出:我今年25岁,存款5000.00元
格式说明符对照表:
| 符号 | 类型 | 示例 |
|---|---|---|
| %d | 整数 | 2023 |
| %f | 浮点数 | 3.14 |
| %s | 字符串 | "Java" |
| %n | 换行符 | (无参数) |
3. 用户输入:Scanner类完全指南
3.1 基础输入流程
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 + "!");
}
}
3.2 不同类型输入处理
Scanner的方法选择取决于输入类型:
| 方法 | 返回类型 | 特点 |
|---|---|---|
| next() | String | 读取到空格/换行符前的内容 |
| nextLine() | String | 读取整行(包含空格) |
| nextInt() | int | 读取整数,可能抛出异常 |
| nextDouble() | double | 读取浮点数 |
| hasNext() | boolean | 检查是否还有输入 |
常见坑点:混合使用nextXXX()和nextLine()时,换行符会被遗留,建议统一用nextLine()接收后转换类型
4. 实战:构建简易计算器
java复制import java.util.Scanner;
public class MiniCalculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("简易计算器(支持+-*/)");
System.out.print("输入第一个数字:");
double num1 = Double.parseDouble(scanner.nextLine());
System.out.print("输入运算符:");
String op = scanner.nextLine();
System.out.print("输入第二个数字:");
double num2 = Double.parseDouble(scanner.nextLine());
switch(op) {
case "+":
System.out.println("结果:" + (num1 + num2));
break;
case "-":
System.out.println("结果:" + (num1 - num2));
break;
case "*":
System.out.println("结果:" + (num1 * num2));
break;
case "/":
if(num2 == 0) {
System.out.println("错误:除数不能为0");
} else {
System.out.println("结果:" + (num1 / num2));
}
break;
default:
System.out.println("不支持的运算符");
}
}
}
5. 异常处理:让程序更健壮
5.1 输入校验模板
java复制Scanner scanner = new Scanner(System.in);
int age = 0;
boolean valid = false;
while(!valid) {
try {
System.out.print("请输入年龄:");
age = Integer.parseInt(scanner.nextLine());
if(age < 0 || age > 120) {
throw new IllegalArgumentException();
}
valid = true;
} catch (NumberFormatException e) {
System.out.println("请输入数字!");
} catch (IllegalArgumentException e) {
System.out.println("年龄应在0-120之间!");
}
}
5.2 常见输入异常类型
| 异常类型 | 触发场景 | 解决方案 |
|---|---|---|
| InputMismatchException | 输入类型与方法不匹配 | 先用nextLine()统一接收 |
| NoSuchElementException | 没有更多输入 | 检查hasNext() |
| IllegalStateException | Scanner已关闭 | 避免重复关闭 |
6. 进阶:文件输入输出
6.1 文件读写示例
java复制import java.io.*;
import java.nio.file.*;
public class FileIO {
public static void main(String[] args) {
// 写入文件
try (PrintWriter writer = new PrintWriter("output.txt")) {
writer.println("这是第一行");
writer.printf("当前时间:%tF %<tT%n", System.currentTimeMillis());
} catch (FileNotFoundException e) {
System.out.println("文件创建失败");
}
// 读取文件
try {
String content = Files.readString(Paths.get("output.txt"));
System.out.println("文件内容:\n" + content);
} catch (IOException e) {
System.out.println("文件读取失败");
}
}
}
6.2 路径处理注意事项
- 相对路径基于项目根目录(IDE中可能是项目文件夹)
- Windows路径用双反斜杠:
C:\\data\\file.txt - 推荐使用Paths.get()构造跨平台路径
7. 调试技巧:输入输出问题排查
-
打印调试法:在关键位置插入System.out.println()
java复制System.out.println("[DEBUG] 当前输入值:" + input); -
IDE调试器:
- 在Scanner调用前设置断点
- 查看System.in的字节流
-
常见问题速查:
- 输入被跳过 → 检查是否有遗留的换行符
- 中文乱码 → 启动时添加
-Dfile.encoding=UTF-8参数 - 文件找不到 → 检查工作目录和路径格式
8. 性能优化:大量IO处理建议
当处理超过1万行的数据时:
-
使用BufferedReader替代Scanner:
java复制BufferedReader reader = new BufferedReader(new FileReader("bigdata.txt")); String line; while ((line = reader.readLine()) != null) { // 处理每行数据 } -
写入时使用BufferedWriter:
java复制BufferedWriter writer = new BufferedWriter(new FileWriter("result.txt")); writer.write("大数据处理结果"); writer.newLine(); // 换行 -
关键参数:
- 缓冲区大小默认8192字符
- 大文件可调整为32768(32KB)
9. 现代Java的输入输出改进
Java 11+新增特性:
-
单行文件读取:
java复制String content = Files.readString(Path.of("file.txt")); -
便捷写入:
java复制Files.writeString(Path.of("output.txt"), "内容"); -
临时文件处理:
java复制Path tempFile = Files.createTempFile("prefix", ".txt");
10. 实战项目:通讯录管理系统
java复制import java.util.*;
import java.io.*;
public class ContactManager {
private static final String FILE_NAME = "contacts.csv";
public static void main(String[] args) {
List<Contact> contacts = loadContacts();
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.println("\n通讯录管理系统");
System.out.println("1. 添加联系人 2. 查看所有 3. 搜索 4. 退出");
System.out.print("请选择:");
String choice = scanner.nextLine();
switch(choice) {
case "1":
addContact(scanner, contacts);
break;
case "2":
listContacts(contacts);
break;
case "3":
searchContact(scanner, contacts);
break;
case "4":
saveContacts(contacts);
return;
default:
System.out.println("无效选择");
}
}
}
// 其他方法实现...
}
这个项目综合运用了:
- 控制台输入输出
- 文件读写
- 集合操作
- 异常处理
建议先实现基础功能,再逐步添加:
- 电话号码格式校验
- 按姓名排序
- 导出不同格式(JSON/XML)
