1日目のゴール
1日目のテーマは
「ミニToDoアプリを“ちゃんとクラス設計して、List で管理し、入力で動かす”感覚をつかむこと」 です。
いきなり完璧なアプリを作るのではなく、
クラスをどう分けるか
タスクを List でどう持つか
コンソールからの入力をどう扱うか
この3つを、シンプルな ToDo アプリを通して体に入れていきます。
機能は最小限です。
タスクを追加する
タスクを一覧表示する
タスクを削除する
今日は「CUI(コンソール)」版でやります。
全体設計を先に“言葉”で決める
どんなクラスが必要かを考える
いきなりコードに行かず、まずは言葉で設計します。
タスク1件分を表すクラス(Task)
タスクの一覧を管理するクラス(TaskManager)
アプリ全体の流れを持つクラス(Main)
この3つに分けると、きれいに整理できます。
Task は「1件分のデータ」
TaskManager は「Task の List を管理する役」
Main は「ユーザーとのやりとり(入力・メニュー)」
という役割分担です。
タスク1件分を表す Task クラス
Task クラスの基本形
まずは「タスク1件」をクラスにします。
public class Task {
String title;
Task(String title) {
if (title == null || title.isEmpty()) {
throw new IllegalArgumentException("タイトルは必須です。");
}
this.title = title;
}
void show(int index) {
System.out.println(index + ": " + title);
}
}
Javaここでやっていることを整理します。
タイトルだけを持つシンプルなタスク
コンストラクタで「空文字や null を防ぐ」show で「自分を表示する」
1日目なので、状態は「タイトルだけ」に絞っています。
あとで「完了フラグ」などを足す余地を残しておくイメージです。
タスク一覧を管理する TaskManager クラス
ArrayList でタスクを持つ
タスクは「何件になるか分からない」ので、ArrayList<Task> で持つのが自然です。
import java.util.ArrayList;
public class TaskManager {
ArrayList<Task> tasks;
TaskManager() {
tasks = new ArrayList<>();
}
}
Javaここでのポイントは、
TaskManager が「タスクの List を抱える役」
Main からは、なるべく tasks を直接触らない
という設計にすることです。
タスクを追加するメソッド
void addTask(String title) {
try {
Task task = new Task(title);
tasks.add(task);
System.out.println("タスクを追加しました: " + title);
} catch (IllegalArgumentException e) {
System.out.println("タスクの追加に失敗しました: " + e.getMessage());
}
}
Javaここで大事なのは、
Task の生成(バリデーション付き)
List への追加
メッセージ表示
を TaskManager の中に閉じ込めていることです。
Main 側は「タイトルを渡すだけ」で済みます。
タスク一覧を表示するメソッド
void showAll() {
System.out.println("=== タスク一覧 ===");
if (tasks.isEmpty()) {
System.out.println("タスクはありません。");
return;
}
for (int i = 0; i < tasks.size(); i++) {
Task t = tasks.get(i);
t.show(i);
}
}
Javaここでのポイントは、
インデックス(0,1,2…)を一緒に表示している
このインデックスを「削除するときの番号」として使う
という設計です。
「番号で指定して削除する」ために、
一覧表示のときに番号を見せています。
タスクを削除するメソッド
void removeTask(int index) {
if (index < 0 || index >= tasks.size()) {
System.out.println("その番号のタスクは存在しません。");
return;
}
Task removed = tasks.remove(index);
System.out.println("タスクを削除しました: " + removed.title);
}
Javaここで重要なのは、
インデックスの範囲チェックを必ずするremove(index) で、その位置のタスクを削除できる
削除された Task を戻り値として受け取れるので、メッセージに使える
という点です。
入力処理の基本:Scanner とメニュー
Scanner でコンソール入力を受け取る
Java で CUI の入力を扱うときの定番が Scanner です。
import java.util.Scanner;
JavaMain でこう使います。
Scanner scanner = new Scanner(System.in);
Javaこれで、キーボードからの入力を読み取れるようになります。
メニューを表示して、ユーザーに選んでもらう
1日目のメニューはシンプルにします。
1: 追加
2: 一覧
3: 削除
0: 終了
これをコードにすると、こうなります。
public class Main {
public static void main(String[] args) {
TaskManager manager = new TaskManager();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println();
System.out.println("=== ミニToDoアプリ ===");
System.out.println("1: タスク追加");
System.out.println("2: タスク一覧");
System.out.println("3: タスク削除");
System.out.println("0: 終了");
System.out.print("番号を選んでください: ");
String line = scanner.nextLine();
if (line.equals("0")) {
System.out.println("終了します。");
break;
} else if (line.equals("1")) {
System.out.print("タスクのタイトルを入力してください: ");
String title = scanner.nextLine();
manager.addTask(title);
} else if (line.equals("2")) {
manager.showAll();
} else if (line.equals("3")) {
manager.showAll();
System.out.print("削除したいタスクの番号を入力してください: ");
String indexStr = scanner.nextLine();
try {
int index = Integer.parseInt(indexStr);
manager.removeTask(index);
} catch (NumberFormatException e) {
System.out.println("番号は整数で入力してください。");
}
} else {
System.out.println("不正な入力です。もう一度選んでください。");
}
}
scanner.close();
}
}
Java入力処理で特に大事なポイント
文字列として受け取ってから解釈する
scanner.nextLine() は「1行まるごと文字列」で受け取ります。
メニュー番号
削除したいタスクの番号
どちらも、まずは String として受け取り、
必要に応じて Integer.parseInt で数値に変換しています。
ここで大事なのは、
入力は「必ず文字列として入ってくる」
「どう解釈するか」は自分で決める
という感覚です。
例外をキャッチしてアプリを落とさない
削除番号のところで、こう書きました。
try {
int index = Integer.parseInt(indexStr);
manager.removeTask(index);
} catch (NumberFormatException e) {
System.out.println("番号は整数で入力してください。");
}
Javaユーザーが「abc」などの変な文字を入れても、
アプリが落ちずにメッセージを出して続行できます。
「入力は信用しない」
「変な入力が来ても落ちないようにする」
これは、アプリを書くときの大事な姿勢です。
1日目のミニToDoアプリ全体像
TaskManager 全体
import java.util.ArrayList;
public class TaskManager {
ArrayList<Task> tasks;
TaskManager() {
tasks = new ArrayList<>();
}
void addTask(String title) {
try {
Task task = new Task(title);
tasks.add(task);
System.out.println("タスクを追加しました: " + title);
} catch (IllegalArgumentException e) {
System.out.println("タスクの追加に失敗しました: " + e.getMessage());
}
}
void showAll() {
System.out.println("=== タスク一覧 ===");
if (tasks.isEmpty()) {
System.out.println("タスクはありません。");
return;
}
for (int i = 0; i < tasks.size(); i++) {
Task t = tasks.get(i);
t.show(i);
}
}
void removeTask(int index) {
if (index < 0 || index >= tasks.size()) {
System.out.println("その番号のタスクは存在しません。");
return;
}
Task removed = tasks.remove(index);
System.out.println("タスクを削除しました: " + removed.title);
}
}
JavaMain 全体(再掲)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
TaskManager manager = new TaskManager();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println();
System.out.println("=== ミニToDoアプリ ===");
System.out.println("1: タスク追加");
System.out.println("2: タスク一覧");
System.out.println("3: タスク削除");
System.out.println("0: 終了");
System.out.print("番号を選んでください: ");
String line = scanner.nextLine();
if (line.equals("0")) {
System.out.println("終了します。");
break;
} else if (line.equals("1")) {
System.out.print("タスクのタイトルを入力してください: ");
String title = scanner.nextLine();
manager.addTask(title);
} else if (line.equals("2")) {
manager.showAll();
} else if (line.equals("3")) {
manager.showAll();
System.out.print("削除したいタスクの番号を入力してください: ");
String indexStr = scanner.nextLine();
try {
int index = Integer.parseInt(indexStr);
manager.removeTask(index);
} catch (NumberFormatException e) {
System.out.println("番号は整数で入力してください。");
}
} else {
System.out.println("不正な入力です。もう一度選んでください。");
}
}
scanner.close();
}
}
Java1日目で絶対に押さえてほしい本質
今日いちばん大事なのは、
「クラス設計・List 管理・入力処理が、“1つのアプリ”の中でちゃんとつながった感覚」 を持てたかどうかです。
Task は「1件分のデータ」
TaskManager は「Task の List を管理する役」
Main は「ユーザーとの会話(入力・メニュー)」
そして、
タスクは ArrayList<Task> で可変長に持つ
一覧表示ではインデックスも一緒に見せる
削除はインデックス指定で行う
入力は文字列で受け取り、自分で解釈する
ここまでが自然に説明できれば、
2日目以降に「完了フラグ」「保存」「優先度」などを足していくときも、
迷わず設計を広げていけます。
もし余裕があれば、
メニューに「何もせず Enter だけ押したらどうなるか」など、
わざと変な入力をして、アプリの振る舞いを観察してみてください。
そこから「次にどんなガードを書きたいか」が見えてきます。

