Java | 基礎文法:メソッド定義

Java Java
スポンサーリンク

メソッド定義の全体像

メソッドは「処理に名前をつけて再利用できるようにする単位」です。入力(引数)を受け取り、必要なら結果(戻り値)を返します。Java では「戻り値の型」「メソッド名」「引数の並び」「本体(処理)」をセットで定義します。設計の肝は「単一責務(1メソッド=1つのはっきりした目的)」「明確な名前」「型の整合」です。


基本構文と各要素

最小の書式と動き

// 戻り値あり
static int add(int a, int b) {
    return a + b;
}

// 戻り値なし(void)
static void greet(String name) {
    System.out.println("Hello, " + name);
}
Java
  • 戻り値の型: 計算結果の型(返さないなら void)。
  • メソッド名: 動詞+目的語で「何をするか」が伝わる名前に。
  • 引数リスト: 型 名 をカンマで並べる。個数は0でも可。
  • 本体: {} 内で処理を書く。戻り値ありなら return が必須。

呼び出しとクラスの文脈

public class Demo {
    public static void main(String[] args) {
        int s = add(3, 8);
        greet("Java"); // "Hello, Java"
        System.out.println(s); // 11
    }

    static int add(int a, int b) { return a + b; }
    static void greet(String name) { System.out.println("Hello, " + name); }
}
Java

main はエントリポイント。static メソッドは「インスタンスを作らずに」クラスから直接呼べます。


引数と戻り値(重要ポイントの深掘り)

値の受け渡しとイミュータブル/ミュータブル

  • 値渡し: Java の引数はすべて「値渡し」。プリミティブは値そのもの、参照型は「参照の値」が渡る。
  • 参照型の変更: 参照先オブジェクトの中身を変えると呼び出し側からも見える。参照そのものを別のインスタンスへ差し替えても、呼び出し元の変数は変わらない。
class Box { int v; }

static void bump(Box b) { b.v++; }       // 中身の変更は反映される
static void reassign(Box b) { b = new Box(); b.v = 999; } // 参照の再代入は呼び出し元に影響しない

Box box = new Box();
bump(box);        // box.v は増える
reassign(box);    // box.v は変わらない
Java

戻り値の設計

  • 単一の意味: 1つのメソッドは1つの意味ある結果を返す。複数の結果が必要なら「結果オブジェクト」を作る。
  • void の使いどころ: 出力や状態変更のみで「計算結果」がないとき。副作用に依存し過ぎない設計が望ましい。
static boolean isAdult(int age) { return age >= 18; }
static String label(int score) {
    if (score >= 80) return "A";
    if (score >= 70) return "B";
    if (score >= 60) return "C";
    return "D";
}
Java

メソッドのバリエーションと設計

オーバーロード(同名・引数違い)

同じ名前で「引数の型・個数・並び」が異なるメソッドを複数定義できます。意味が近い処理を一つの名前でまとめられます。

static int sum(int a, int b) { return a + b; }
static double sum(double a, double b) { return a + b; }
static int sum(int... nums) {
    int s = 0;
    for (int n : nums) s += n;
    return s;
}
Java
  • 可変長引数(int...): 0個以上の引数を受け取れる。配列として中で扱う。複雑な組み合わせが必要なら「配列/コレクションをそのまま受ける」方が明快。

アクセス修飾子と static/instance

public class Counter {
    private int value;                 // インスタンスの状態
    public void inc() { value++; }     // インスタンスメソッド(this を使う)
    public int get() { return value; }

    public static int add(int a, int b) { return a + b; } // クラスメソッド
}
Java
  • public / private / package-private / protected: 外からの見え方を制御。原則は「最小公開(必要最小限だけ public)」。
  • static: インスタンス不要。ユーティリティ・純粋関数に向く。インスタンスの状態(this)には触れられない。
  • インスタンスメソッド: 個別の状態を扱う。オブジェクト指向の中心。

例外・検証・契約(重要ポイントの深掘り)

前提の検証(早期リターン)

メソッドの入口で「不正な入力」を弾くと、以降のロジックがシンプルになります。

static int divide(int a, int b) {
    if (b == 0) throw new IllegalArgumentException("b must not be 0");
    return a / b;
}
Java
  • チェック例外 vs 実行時例外: IOException などは宣言/捕捉が必要(チェック例外)。入力の不正は IllegalArgumentException など実行時例外が適切。
  • 契約の明示: 引数の前提を Javadoc や名前で表現。「null を許容するか」「範囲はどうか」を決めて一貫性を保つ。

返り値の null と代替

  • 返り値に null を返すなら呼び出し側のガードが必要。代替として「空オブジェクト」「Optional(API設計向け)」を検討。
static String findOrDefault(String[] arr, String key, String def) {
    for (String s : arr) if (key.equals(s)) return s;
    return def; // nullを返さずデフォルトで安全
}
Java

スコープ・ライフサイクルと副作用

変数のスコープ

  • ローカル変数: メソッド内だけ有効。外から見えない。副作用の拡散を防ぐ。
  • フィールド(インスタンス/クラス変数): メソッドをまたいで状態を保持。必要最小限にし、同期や一貫性に注意。
static void demo() {
    int x = 10;      // ローカル(このメソッド内だけ)
    // System.out.println(y); // 他メソッドのローカルは見えない
}
Java

副作用の管理

  • 純粋関数を優先: 入力→出力が明確で、外部状態に依存しない/変更しない。
  • I/O や状態変更: 目的が明確なメソッドに閉じ込める。名前に副作用を反映(例:save、update、print)。

実用例で身につける

例 1: 名前とスコアからラベル生成

public class Labeler {
    public static void main(String[] args) {
        System.out.println(makeLabel("sato", 75)); // sato:B
    }

    static String makeLabel(String name, int score) {
        return name + ":" + grade(score);
    }

    static String grade(int score) {
        if (score >= 80) return "A";
        if (score >= 70) return "B";
        if (score >= 60) return "C";
        return "D";
    }
}
Java

例 2: 可変長引数で合計

public class VarargsSum {
    public static void main(String[] args) {
        System.out.println(sum(1,2,3));        // 6
        System.out.println(sum());              // 0
        System.out.println(sum(new int[]{4,5})); // オーバーロードで配列も
    }

    static int sum(int... nums) {
        int s = 0;
        for (int n : nums) s += n;
        return s;
    }
    static int sum(int[] nums) { return sum(java.util.Arrays.stream(nums).toArray()); }
}
Java

例 3: インスタンスメソッドで状態を管理

public class Counter {
    private int value;

    public void inc() { value++; }
    public int get() { return value; }

    public static void main(String[] args) {
        Counter c = new Counter();
        c.inc(); c.inc();
        System.out.println(c.get()); // 2
    }
}
Java

設計の指針(重要部分のまとめ)

  • メソッドは「単一責務」と「明快な名前」。引数と戻り値で意図を表現し、副作用は最小限に。
  • 入口で前提を検証し、異常は早期に弾く。返り値の null は避け、代替や例外で契約を明確化。
  • オーバーロードは「同じ意味の異バリエーション」に限定。可変長引数は便利だが乱用しない。
  • static はユーティリティ・純粋関数、インスタンスメソッドは状態を扱う。公開範囲は最小に。
  • スコープを意識して、ローカル変数で処理を閉じる。読みやすさとテスト容易性が上がる。

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