メソッド呼び出しの全体像
メソッド呼び出しは「名前のついた処理を実行し、必要なら結果を受け取る」行為です。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
}
}
Javastatic は「インスタンス不要」。ユーティリティ関数や純粋計算に向いています。
インスタンスメソッドを呼ぶ
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) { /* クラス内のみ */ }
}
Javapublic は外部公開、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 の契約を明確にし、呼び出し側から見て安全なインターフェースを心がける。公開範囲は最小限に。
