Java | 2週間で身につく、アプリを作りながら学ぶJavaの基本 - 6日目

Java Java
スポンサーリンク

6日目のゴールとテーマ

6日目のテーマは
「メソッドで“処理を分ける力”を身につけて、コードを読みやすく育てる」 です。

5日目までで、あなたはすでに

入力を受け取る
条件分岐で動きを変える
ループで繰り返す
ArrayListで増えたり減ったりするデータを扱う

ここまで来ています。

今日は、ここに

「メソッド」という“自分で作る命令”を使って
長くなってきた main を分解し
読みやすく・直しやすく・再利用しやすくする

という、一段上の「設計の感覚」を足していきます。


そもそもメソッドって何か

「処理に名前をつけて、ひとまとまりにするもの」

メソッドは、簡単に言うと

「この処理に名前をつけて、あとから何度でも呼び出せるようにしたもの」

です。

例えば、こんなコードがあったとします。

System.out.println("=== 簡易ToDoリスト ===");
System.out.println("1: タスクを追加する");
System.out.println("2: タスク一覧を表示する");
System.out.println("3: タスクを削除する");
System.out.println("0: 終了する");
System.out.print("番号を選んでください: ");
Java

これを main の中にベタッと書くのではなく、

printMenu();
Java

と1行で書けたら、かなりスッキリしますよね。

その「printMenu」という“自分で作る命令”が、メソッドです。


一番シンプルなメソッドの形

引数なし・戻り値なしのメソッド

まずは、いちばんシンプルな形からいきます。

public static void printMenu() {
    System.out.println("=== 簡易ToDoリスト ===");
    System.out.println("1: タスクを追加する");
    System.out.println("2: タスク一覧を表示する");
    System.out.println("3: タスクを削除する");
    System.out.println("0: 終了する");
    System.out.print("番号を選んでください: ");
}
Java

これを main の外(同じクラスの中)に書いておき、
main の中からこう呼びます。

public static void main(String[] args) {
    printMenu();
    // ここで入力を受け取る処理などを続ける
}
Java

形を分解してみます。

public static
→ ひとまず「main と同じように書く」と覚えてOK
→ 後半で意味を少しだけ触れますが、今日は深追いしなくて大丈夫です。

void
→ 「何も値を返さない」メソッド
→ 「表示するだけ」「処理するだけ」のときによく使う

printMenu
→ メソッド名。自分で決める。
→ 「何をするメソッドか」が分かる名前にするのが超重要。

()
→ 引数(あとで説明)を入れる場所。今は何もなし。

{ ... }
→ この中に「そのメソッドがやる処理」を書く。

この「形」を、まずは体で覚えてしまいましょう。


引数付きメソッドで「外から値を渡す」

「この値を使って処理してね」と渡すイメージ

次に、「外から値を渡して、その値を使って処理する」メソッドを考えます。

例えば、「点数を渡したら、その点数に応じてメッセージを表示する」メソッド。

public static void printScoreMessage(int score) {
    System.out.println("点数: " + score);

    if (score >= 80) {
        System.out.println("よくできました!");
    } else if (score >= 60) {
        System.out.println("まずまずです。");
    } else {
        System.out.println("もう少しがんばりましょう。");
    }
}
Java

これを main からこう呼びます。

public static void main(String[] args) {
    printScoreMessage(85);
    printScoreMessage(70);
    printScoreMessage(40);
}
Java

ここでの重要ポイントを深掘りします。

int score
→ これが「引数」です。
→ 「このメソッドを呼ぶときに、int 型の値を1つ渡してください」という意味。

printScoreMessage(85);
→ 85 が score に入る。
→ メソッドの中では、score という名前でその値を使える。

引数は、「メソッドに渡す材料」です。
材料が違えば、同じメソッドでも違う結果を出せます。


戻り値付きメソッドで「計算結果を返す」

「処理した結果を、呼び出し元に返す」

次は、「計算して、その結果を返す」メソッドです。

例えば、「2つの整数の合計を返す」メソッド。

public static int add(int a, int b) {
    int result = a + b;
    return result;
}
Java

これを main からこう使います。

public static void main(String[] args) {
    int x = add(3, 5);
    int y = add(10, 20);

    System.out.println("x = " + x);  // 8
    System.out.println("y = " + y);  // 30
}
Java

形を分解します。

public static int add(int a, int b)
int は「このメソッドは int 型の値を返します」という意味。
ab は引数。呼び出し時に渡された値が入る。

return result;
→ 「このメソッドの“答え”として result を返します」という命令。
→ 戻り値の型(ここでは int)と、返す値の型が一致している必要がある。

戻り値付きメソッドは、

「何かを計算して、その結果を使いたいとき」
「同じ計算を何度もしたいとき」

にとても役立ちます。


mainが長くなってきたら「分けどき」

「1つのメソッドに“何でもかんでも”詰め込まない」

5日目の ToDo リストの main を思い出してみてください。
メニュー表示
入力
追加処理
一覧表示
削除処理

全部が main の中に入っていて、かなり長くなっていました。

長い main の問題は、

どこで何をしているか、一目で分かりにくい
一部だけ直したいときに、探すのが大変
同じような処理が重複しやすい

というところです。

そこで、「役割ごとにメソッドに分ける」という発想が出てきます。

例えば、

メニューを表示する → printMenu
タスク一覧を表示する → printTasks
タスクを追加する → addTask
タスクを削除する → removeTask

のように分けていくと、
main は「アプリ全体の流れ」だけを書く場所になります。


ToDoアプリをメソッドで分解してみる

まずはメニュー表示と一覧表示をメソッド化

5日目の ToDo アプリを、少しずつメソッドに分けていきます。

まずは、メニュー表示と一覧表示から。

import java.util.ArrayList;
import java.util.Scanner;

public class Main {

    public static void printMenu() {
        System.out.println("=== 簡易ToDoリスト ===");
        System.out.println("1: タスクを追加する");
        System.out.println("2: タスク一覧を表示する");
        System.out.println("3: タスクを削除する");
        System.out.println("0: 終了する");
        System.out.print("番号を選んでください: ");
    }

    public static void printTasks(ArrayList<String> tasks) {
        if (tasks.isEmpty()) {
            System.out.println("タスクは登録されていません。");
        } else {
            System.out.println("=== タスク一覧 ===");
            for (int i = 0; i < tasks.size(); i++) {
                System.out.println((i + 1) + ": " + tasks.get(i));
            }
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        ArrayList<String> tasks = new ArrayList<>();

        while (true) {
            printMenu();

            int choice = scanner.nextInt();
            scanner.nextLine();  // 改行を読み飛ばす

            if (choice == 0) {
                System.out.println("アプリを終了します。");
                break;
            } else if (choice == 1) {
                // 追加処理(あとでメソッド化)
            } else if (choice == 2) {
                printTasks(tasks);
            } else if (choice == 3) {
                // 削除処理(あとでメソッド化)
            } else {
                System.out.println("その番号は無効です。");
            }

            System.out.println();
        }
    }
}
Java

ここでの重要ポイントを深掘りします。

printTasks(ArrayList<String> tasks)
→ 引数として tasks を受け取っている
→ main の中の tasks を、そのまま渡して使っている

メソッドに「必要なものだけを渡す」ことで、
メソッドの中身が「外の変数にベタベタ依存しない」状態になります。
これは、コードを理解しやすくするうえで、とても大事な考え方です。


追加処理と削除処理もメソッドにする

「1つのメソッドは、1つの“意味のある仕事”だけ」

次に、タスク追加と削除もメソッドに分けます。

public class Main {

    public static void addTask(Scanner scanner, ArrayList<String> tasks) {
        System.out.print("追加するタスクを入力してください: ");
        String task = scanner.nextLine();
        if (task.isEmpty()) {
            System.out.println("空のタスクは追加できません。");
        } else {
            tasks.add(task);
            System.out.println("タスクを追加しました。");
        }
    }

    public static void removeTask(Scanner scanner, ArrayList<String> tasks) {
        if (tasks.isEmpty()) {
            System.out.println("削除できるタスクがありません。");
            return;
        }

        System.out.println("削除するタスクの番号を入力してください:");
        for (int i = 0; i < tasks.size(); i++) {
            System.out.println((i + 1) + ": " + tasks.get(i));
        }

        System.out.print("番号: ");
        int index = scanner.nextInt();
        scanner.nextLine();  // 改行を読み飛ばす

        int realIndex = index - 1;

        if (realIndex < 0 || realIndex >= tasks.size()) {
            System.out.println("その番号のタスクは存在しません。");
        } else {
            String removed = tasks.remove(realIndex);
            System.out.println("タスク「" + removed + "」を削除しました。");
        }
    }

    // printMenu, printTasks, main はさっきのまま
}
Java

main はこうなります。

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    ArrayList<String> tasks = new ArrayList<>();

    while (true) {
        printMenu();

        int choice = scanner.nextInt();
        scanner.nextLine();  // 改行を読み飛ばす

        if (choice == 0) {
            System.out.println("アプリを終了します。");
            break;
        } else if (choice == 1) {
            addTask(scanner, tasks);
        } else if (choice == 2) {
            printTasks(tasks);
        } else if (choice == 3) {
            removeTask(scanner, tasks);
        } else {
            System.out.println("その番号は無効です。");
        }

        System.out.println();
    }
}
Java

かなりスッキリしましたよね。

main は、

メニューを表示する
入力を受け取る
番号に応じて「どのメソッドを呼ぶか」を決める

という「アプリ全体の流れ」だけを書いています。


引数に何を渡すかを意識する

「このメソッドが仕事をするのに必要なものだけ渡す」

addTask と removeTask の定義をもう一度見てみます。

public static void addTask(Scanner scanner, ArrayList<String> tasks)
public static void removeTask(Scanner scanner, ArrayList<String> tasks)
Java

どちらも、Scanner と tasks を引数として受け取っています。

ここで大事なのは、

「このメソッドが仕事をするのに、何が必要か?」

という視点です。

タスクを追加するには、

ユーザーから文字列を入力するための Scanner
タスクを追加する先の ArrayList

が必要です。
だから、その2つを引数として受け取っています。

メソッドを設計するときは、

このメソッドは何をするのか
そのために、外から何を渡してもらう必要があるか
結果を返す必要があるか(戻り値がいるか)

を考えるクセをつけると、一気にレベルが上がります。


public static の「static」を少しだけ理解する

「インスタンスを作らずに呼べるメソッド」

ここまで、メソッドの定義にずっと public static を付けてきました。

public は「どこからでも呼べるようにする」という意味でしたが、
static は「クラスにくっついているメソッド」という意味です。

今は、

Main.addTask(...)
Main.printMenu()

のように、「Main クラスに属するメソッド」として使っています。

本来、Javaでは

クラスの“実体”(インスタンス)を new で作って
そのインスタンスに対してメソッドを呼ぶ

というスタイルが基本ですが、
2週間コースの前半では、まず static メソッドで

「処理を分ける感覚」
「引数と戻り値の感覚」

を身につけることを優先しています。

後半で「クラスとオブジェクト」をやるときに、
「static じゃないメソッド」の世界に進んでいきます。


6日目のミニアプリ:メソッド分割版ToDoリスト

「mainは“司令塔”、メソッドは“現場の担当者”」

ここまでの内容をまとめた、完成形に近いコードをもう一度通して載せます。

import java.util.ArrayList;
import java.util.Scanner;

public class Main {

    public static void printMenu() {
        System.out.println("=== 簡易ToDoリスト ===");
        System.out.println("1: タスクを追加する");
        System.out.println("2: タスク一覧を表示する");
        System.out.println("3: タスクを削除する");
        System.out.println("0: 終了する");
        System.out.print("番号を選んでください: ");
    }

    public static void printTasks(ArrayList<String> tasks) {
        if (tasks.isEmpty()) {
            System.out.println("タスクは登録されていません。");
        } else {
            System.out.println("=== タスク一覧 ===");
            for (int i = 0; i < tasks.size(); i++) {
                System.out.println((i + 1) + ": " + tasks.get(i));
            }
        }
    }

    public static void addTask(Scanner scanner, ArrayList<String> tasks) {
        System.out.print("追加するタスクを入力してください: ");
        String task = scanner.nextLine();
        if (task.isEmpty()) {
            System.out.println("空のタスクは追加できません。");
        } else {
            tasks.add(task);
            System.out.println("タスクを追加しました。");
        }
    }

    public static void removeTask(Scanner scanner, ArrayList<String> tasks) {
        if (tasks.isEmpty()) {
            System.out.println("削除できるタスクがありません。");
            return;
        }

        System.out.println("削除するタスクの番号を入力してください:");
        for (int i = 0; i < tasks.size(); i++) {
            System.out.println((i + 1) + ": " + tasks.get(i));
        }

        System.out.print("番号: ");
        int index = scanner.nextInt();
        scanner.nextLine();  // 改行を読み飛ばす

        int realIndex = index - 1;

        if (realIndex < 0 || realIndex >= tasks.size()) {
            System.out.println("その番号のタスクは存在しません。");
        } else {
            String removed = tasks.remove(realIndex);
            System.out.println("タスク「" + removed + "」を削除しました。");
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        ArrayList<String> tasks = new ArrayList<>();

        while (true) {
            printMenu();

            int choice = scanner.nextInt();
            scanner.nextLine();  // 改行を読み飛ばす

            if (choice == 0) {
                System.out.println("アプリを終了します。");
                break;
            } else if (choice == 1) {
                addTask(scanner, tasks);
            } else if (choice == 2) {
                printTasks(tasks);
            } else if (choice == 3) {
                removeTask(scanner, tasks);
            } else {
                System.out.println("その番号は無効です。");
            }

            System.out.println();
        }
    }
}
Java

ここまで来ると、
「アプリの全体像」と「各機能の中身」がきれいに分かれています。

main
→ 司令塔。どのメソッドをいつ呼ぶかを決める。

printMenu / printTasks / addTask / removeTask
→ 現場の担当者。それぞれの仕事だけに集中している。

この構造が作れるようになると、
アプリが大きくなっても、頭の中がぐちゃぐちゃになりにくくなります。


6日目で一番大事な感覚

「メソッドは“読みやすさ”と“育てやすさ”のための武器」

今日あなたに持ってほしい感覚はこれです。

メソッドは、単に「コードを短くするための道具」ではありません。

何をしているかが一目で分かるようにする
同じ処理を何度も書かなくて済むようにする
一部分だけを安心して直せるようにする

つまり、「読みやすさ」と「育てやすさ」のための武器です。

「この塊、名前をつけられそうだな」と感じたら、それはメソッドにするサインです。


6日目のまとめと、7日目への予告

今日やったことを短く整理すると、

メソッドは「処理に名前をつけて、ひとまとまりにしたもの」
引数で「外から材料を渡す」
戻り値で「計算結果を返す」
main が長くなってきたら、役割ごとにメソッドに分ける
ToDo アプリをメソッド分割して、読みやすい構造にできた

7日目からはいよいよ、「クラス」と「オブジェクト」の世界に入っていきます。
今日までに身につけた「メソッドの感覚」が、そのままクラス設計の土台になります。

タイトルとURLをコピーしました