最直接的落地方式是用ArrayList存任务、Scanner读输入,但应封装Task类含description和isDone字段,按序号删除、统一用nextLine()转数字并校验,避免static变量共享状态。

用 ArrayList + Scanner 实现控制台待办列表
Java 初级项目最直接的落地方式,就是避开 GUI 和数据库,先用 ArrayList 存任务、Scanner 读用户输入。这样能聚焦在逻辑组织和基础语法上,而不是被环境配置卡住。
常见错误是把任务状态(如“已完成”)硬编码成字符串拼接,导致后期无法筛选或修改。建议一开始就用简单封装:哪怕只是自定义一个 Task 类,带 description 和 isDone 两个字段。
- 每次添加任务时,用
list.add(new Task(input)),别用list.add(input) - 显示列表时,遍历用
for (Task t : tasks),输出前检查t.isDone,打勾(✓)或叉(✗)比写“true/false”更直观 - 删除任务别用
list.remove(input)——它删的是值匹配项,容易误删;改用按序号删:list.remove(index - 1)(用户看到的是 1 起始)
避免 Scanner.nextLine() 吃掉回车的坑
当混合使用 scanner.nextInt() 和 scanner.nextLine() 时,后者常读到空行。这是因为 nextInt() 不消费换行符,nextLine() 紧接着就把它当作了输入。
典型场景:让用户选菜单编号(int choice = scanner.nextInt()),再输任务内容(String desc = scanner.nextLine()),结果 desc 总是空。
立即学习“Java免费学习笔记(深入)”;
- 修复方法统一:所有输入都用
nextLine(),数字转用Integer.parseInt(scanner.nextLine().trim()) - 加
.trim()防用户多敲空格导致NumberFormatException - 包一层
try-catch捕获NumberFormatException,提示“请输入有效数字”,别让程序直接崩
用 static 方法组织功能,但别滥用 static 变量
初学者容易把整个任务列表声明为 static List,看似方便所有方法访问,实则埋下测试和扩展隐患:多个实例会共享同一份数据,单元测试互相污染,后续加用户隔离也无从下手。
更合理的做法是把核心逻辑放进一个非静态类(如 TodoApp),用实例变量存 tasks,只把交互逻辑(如打印菜单、读选项)抽成 static 工具方法。
public class TodoApp { private Listtasks = new ArrayList(); } -
private static void printMenu() { ... }—— 这类纯展示/IO 方法可以 static - 主流程写在
public void run()里,用new TodoApp().run()启动
public class TodoApp {
private List tasks = new ArrayList<>();
public void run() {
Scanner scanner = new Scanner(System.in);
while (true) {
printMenu();
int choice = parseChoice(scanner);
if (choice == 0) break;
handleChoice(choice, scanner);
}
scanner.close();
}
private void handleChoice(int choice, Scanner scanner) {
switch (choice) {
case 1 -youjiankuohaophpcn addTask(scanner);
case 2 -youjiankuohaophpcn listTasks();
case 3 -youjiankuohaophpcn markDone(scanner);
default -youjiankuohaophpcn System.out.println("无效选项");
}
}
private void addTask(Scanner scanner) {
System.out.print("输入任务: ");
String desc = scanner.nextLine().trim();
if (!desc.isEmpty()) tasks.add(new Task(desc));
}}
真正难的不是写完功能,而是决定哪些状态该属于实例、哪些输入要校验、哪些异常不能吞掉。这些取舍点,往往比语法本身更影响后续可维护性。










