Java | 基礎文法:メソッド呼び出し

Java Java
スポンサーリンク

メソッド呼び出しの全体像

メソッド呼び出しは「名前のついた処理を実行し、必要なら結果を受け取る」行為です。Java では「インスタンスメソッド(対象オブジェクトに対して呼ぶ)」と「static メソッド(クラスから直接呼ぶ)」の2種類があります。引数は左から右へ評価され、Java の引数受け渡しはすべて「値渡し」です(プリミティブは値そのもの、参照型は参照の値)。


基本形と2種類の呼び出し

static メソッドを呼ぶ

public class MathUtil {
    static int add(int a, int b) { return a + b; }
}

public class Demo {
    public static void main(String[] args) {
        int s = MathUtil.add(3, 8); // クラス名.メソッド名
        System.out.println(s);      // 11
    }
}
Java

static は「インスタンス不要」。ユーティリティ関数や純粋計算に向いています。

インスタンスメソッドを呼ぶ

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

public class Demo {
    public static void main(String[] args) {
        Counter c = new Counter();  // インスタンス生成
        c.inc();                    // 対象 c に対して呼ぶ
        System.out.println(c.get()); // 1
    }
}
Java

インスタンスメソッドは「そのオブジェクトの状態」に作用します。this を内部で参照できます。


引数評価と値渡し(重要ポイントの深掘り)

左から右へ評価される

int x = 1;
int y = 2;
int r = add(x++, x + y); // 先に x++(x=2)を評価→次に x+y(2+2=4)
Java

引数は左から右へ順番に評価されます。副作用(++ など)を混ぜると読みづらくなるため、事前に変数へ分解してから渡すと安全です。

値渡しの本質

class Box { int v; }
static void bump(Box b) { b.v++; }             // 中身変化は呼び出し元に見える
static void reassign(Box b) { b = new Box(); } // 参照の差し替えは呼び出し元に影響しない

Box box = new Box();
bump(box);      // box.v が増える(参照先の状態を変更)
reassign(box);  // box は同じ参照のまま(値渡し)
Java

「参照先の中身」は変更が反映されますが、「参照そのものの再代入」は呼び出し元へ伝播しません。


戻り値と制御フロー

戻り値の受け取りと無視

int s = MathUtil.add(5, 7); // 受け取る
System.out.println(s);

MathUtil.add(1, 2);         // 受け取らず副作用だけ期待するのは避ける
Java

戻り値があるなら、結果を使う設計にします。副作用に依存する設計は読みづらく、テストが難しくなります。

連鎖(メソッドチェーン)

String label = "java"
        .toUpperCase()     // "JAVA"
        .concat(" / ")     // "JAVA / "
        .concat("fun");    // "JAVA / fun"
Java

戻り値が同じ型や関連型なら、連鎖で読みやすく書けます。可変オブジェクト(StringBuilder など)は「その場で変更」される点を理解して使い分けます。


オーバーロード解決と可変長引数(重要ポイントの深掘り)

同名・引数違いの選択

static int sum(int a, int b) { return a + b; }
static double sum(double a, double b) { return a + b; }

var r1 = sum(3, 4);     // int 版が選ばれる
var r2 = sum(3.0, 4.0); // double 版が選ばれる
Java

コンパイラは「最も適したシグネチャ」を選びます。曖昧さがあるとコンパイルエラーになるため、意図が伝わる型で呼びます。必要なら明示キャストで解決します。

可変長引数の呼び方

static int sum(int... nums) {
    int s = 0;
    for (int n : nums) s += n;
    return s;
}

sum();          // 0 個
sum(1, 2, 3);   // 可変個
sum(new int[]{4, 5}); // 配列を渡す
Java

呼び出し側は「列挙」でも「配列」でも渡せます。複雑な組み合わせが必要なら、コレクションや明示配列で渡す方が読みやすくなります。


アクセス、パッケージ、他クラスからの呼び出し

修飾子による可視性

public class Util {
    public static int add(int a, int b) { return a + b; } // どこからでも
    private static void log(String s) { /* クラス内のみ */ }
}
Java

public は外部公開、private はクラス内限定。必要最小限の公開に絞ると、安全で保守しやすい設計になります。

同一パッケージ外から呼ぶ

package app.util;
public class Greeter { public static void hi(String name) { System.out.println("Hi " + name); } }

package app.main;
import app.util.Greeter;

public class Demo {
    public static void main(String[] args) {
        Greeter.hi("Sato"); // インポートして呼ぶ
    }
}
Java

別パッケージのクラスは import してから クラス名.メソッド名 で呼びます。アクセス修飾子が公開されている必要があります。


例外、null 安全、契約の守り方(重要ポイントの深掘り)

例外の扱い

static int divide(int a, int b) {
    if (b == 0) throw new IllegalArgumentException("b must not be 0");
    return a / b;
}

try {
    int r = divide(10, 0);
} catch (IllegalArgumentException e) {
    System.out.println(e.getMessage());
}
Java

呼び出し側は「起こりうる例外」を前提に設計します。チェック例外(IOException など)は呼び出し側で捕捉または throws 宣言が必要です。

null のガードと既定値

static String safeUpper(String s) {
    return (s != null) ? s.toUpperCase() : "";
}

System.out.println(safeUpper(null)); // ""
Java

呼び出し側に優しい契約を心がけます。返り値で null を返す設計なら、呼び出し側でガードを入れることが前提になります。


実用例で身につける

例 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 Chain {
    public static void main(String[] args) {
        String s = "java".trim().toUpperCase().replace("A", "@");
        System.out.println(s); // J@V@
    }
}
Java

例 3: 他クラスの static とインスタンスを呼ぶ

class MathUtil {
    static int add(int a, int b) { return a + b; }
}

class Counter {
    private int v;
    void inc() { v++; }
    int get() { return v; }
}

public class CallDemo {
    public static void main(String[] args) {
        int s = MathUtil.add(3, 4);   // static
        Counter c = new Counter();    // インスタンス
        c.inc();
        System.out.println(s + c.get()); // 8
    }
}
Java

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

  • static は「インスタンス不要の純粋処理」、インスタンスメソッドは「対象の状態に作用」。使い分けを明確にする。
  • 引数は左から右へ評価。副作用を混ぜず、事前に値を準備して渡すと読みやすい。Java は値渡しであることを前提にする。
  • 戻り値を活かして設計し、連鎖は「不変の戻り値」に向いている。可変オブジェクトの副作用には注意。
  • オーバーロードは曖昧さを避け、可変長引数は使いすぎない。必要なら明示キャストや配列/コレクションで意図を伝える。
  • 例外と null の契約を明確にし、呼び出し側から見て安全なインターフェースを心がける。公開範囲は最小限に。

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