
本文详解如何使用 scanner 安全读取用户输入的汽车品牌与型号,构建 arraylist,并按规范顺序输出全部车辆信息及总数,避免无限等待、空指针和逻辑错位问题。
本文详解如何使用 scanner 安全读取用户输入的汽车品牌与型号,构建 arraylist,并按规范顺序输出全部车辆信息及总数,避免无限等待、空指针和逻辑错位问题。
在 Java 中,通过 Scanner 从标准输入逐行读取汽车品牌(make)和型号(model)并存入 ArrayList<Car> 是常见需求,但原始代码存在三处关键缺陷:
- hasNext() 无法可靠终止输入:该方法阻塞等待新输入,在控制台交互中不会因换行或空行自动返回 false,导致程序卡死;
- 对象初始化与赋值顺序错误:Car 构造函数中 this.make = make; 引用未初始化的局部变量,造成 null 赋值;
- 输出逻辑混乱:for 循环内重复打印 "There are X cars",且总数输出位置错误,不符合题目要求的“先列全部车型,再统一输出总数”。
✅ 正确实现:分步解析
1. 安全输入终止机制 —— 使用空行判断
应以空行作为输入结束标志,而非 -1 字符串(易出错)或 hasNext()(不可靠)。推荐使用 do-while 循环配合 nextLine():
Scanner scan = new Scanner(System.in);
List<Car> cars = new ArrayList<>();
String make, model;
do {
make = scan.nextLine().trim(); // 去除首尾空格,增强健壮性
if (make.isEmpty()) break; // 空行即终止
model = scan.nextLine().trim();
if (model.isEmpty()) break; // 防止仅输入品牌无型号
cars.add(new Car(make, model));
} while (true);
scan.close();⚠️ 注意:nextLine() 比 next() 更适合读取含空格的字符串(如 "Honda Fit"),且必须成对调用,避免因 nextInt() 等遗留换行符导致后续 nextLine() 读取为空。
2. 优化 Car 类 —— 添加构造函数与 toString()
避免默认构造函数中的未初始化引用错误,并简化对象创建与输出:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
public class Car {
private String make, model;
public Car(String make, String model) {
this.make = make;
this.model = model;
}
// getter/setter 略(保持原有逻辑)
@Override
public String toString() {
return make + " " + model; // 直接支持 System.out.println(car)
}
}3. 规范化输出 —— 分离遍历与统计
题目明确要求输出格式为:
Honda Fit Toyota Corolla Mazda Axela There are 3 cars
因此需将逐项打印与总数汇总严格分离:
// 先完整输出所有汽车信息(每车一行)
for (Car car : cars) {
System.out.println(car); // 自动调用 toString()
}
// 再统一输出总数(仅一次!)
System.out.printf("There are %d cars%n", cars.size());? 提示:使用 printf 替代 format 更简洁;%n 是平台安全的换行符,优于 \n。
✅ 最终可运行代码整合
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
List<Car> cars = new ArrayList<>();
String make, model;
do {
make = scan.nextLine().trim();
if (make.isEmpty()) break;
model = scan.nextLine().trim();
if (model.isEmpty()) break;
cars.add(new Car(make, model));
} while (true);
scan.close();
for (Car car : cars) {
System.out.println(car);
}
System.out.printf("There are %d cars%n", cars.size());
}
}? 关键总结
- 输入终止:永远优先用 nextLine().trim().isEmpty() 判断空行,而非 hasNext() 或魔法字符串;
- 对象安全:构造函数中直接传参赋值,杜绝 this.x = x 引用未定义变量;
- 输出顺序:循环只负责展示数据,统计信息必须在循环外单独输出;
- 健壮性提升:.trim() 处理多余空格,%n 保证跨平台换行,@Override toString() 简化打印逻辑。
遵循以上原则,即可稳定、清晰、符合题意地完成汽车列表的录入与展示任务。

















