Static メソッドの全体像
static メソッドは「クラスに属するメソッド」で、インスタンス(new で作るオブジェクト)を介さずに呼び出せます。数値計算や文字列整形など「個別の状態に依存しない処理」を、クラス名から直接使える形にするのが目的です。オブジェクトのフィールド(this)には触れられないため、「入力(引数)→出力(戻り値)」の純粋な関数として設計するのが基本です。
基本構文と呼び出し方
定義と呼び出しの最小例
public class MathUtil {
public static int add(int a, int b) {
return a + b;
}
}
Javapublic class Demo {
public static void main(String[] args) {
int s = MathUtil.add(3, 8); // クラス名.メソッド名で直接呼ぶ
System.out.println(s); // 11
}
}
Javastatic を付けると「インスタンス不要」で呼べます。メソッドの中で this は使えません(そもそもインスタンスに紐づかないため)。
インスタンスメソッドとの違い(対比)
class Counter {
private int value;
public void inc() { value++; } // インスタンスメソッド(this が使える)
public int get() { return value; }
public static int add(int a, int b) { // static メソッド(状態に触れない)
return a + b;
}
}
Java- インスタンスメソッドはオブジェクトの状態を操作します。
new Counter()から呼びます。 - static メソッドは状態に触れない計算やユーティリティに使い、
Counter.add(...)のように呼びます。
重要ポイントの深掘り:いつ static を使うか
単一責務の純粋処理に最適
「引数だけで結果が決まる」変換・検証・計算は static が最も読みやすく、安全です。テストも簡単で、依存が少ないため再利用性が高まります。
public class Strings {
public static boolean isAsciiDigit(char ch) {
return ch >= '0' && ch <= '9';
}
}
Javaユーティリティクラスの作り方
ユーティリティを集約する場合は、状態を持たず、すべて static で提供します。インスタンス化を防ぐために private コンストラクタを置くのが定石です。
public final class Util {
private Util() {} // 生成禁止
public static String joinWithComma(String... parts) {
if (parts == null || parts.length == 0) return "";
StringBuilder sb = new StringBuilder(parts[0]);
for (int i = 1; i < parts.length; i++) sb.append(", ").append(parts[i]);
return sb.toString();
}
}
Javaエントリポイント main も static
public class App {
public static void main(String[] args) {
System.out.println("Hello");
}
}
JavaJVM が最初に呼ぶのは public static void main(String[] args)。インスタンス不要で起動できるのが理由です。
重要ポイントの深掘り:static と状態、テスト容易性
static フィールドに依存しない設計
static フィールド(クラス変数)に依存すると、グローバル状態の共有でバグやテストの難しさを招きます。static メソッドは「引数→戻り値」に閉じると、並行実行でも安全です。
public class Price {
private static double taxRate = 0.1; // 共有状態は注意が必要
public static int withTax(int price) {
return (int) Math.round(price * (1 + taxRate));
}
}
Java上のような共有状態は「設定変更の影響範囲が広い」ため、必要最小限にし、変更パスを明示します。理想は「税率も引数で受ける」純粋関数です。
public class Price {
public static int withTax(int price, double taxRate) {
return (int) Math.round(price * (1 + taxRate));
}
}
Javaテストがしやすい理由
依存が少ない(this を使わない・外部状態に触れない)ため、static メソッドは単体テストがシンプルです。モックも不要で、単純な入出力の検証に集中できます。
重要ポイントの深掘り:制約とアンチパターン
this・オーバーライド不可
static は this に触れられず、継承しても「オーバーライドの対象にならない」ため、ポリモーフィズムを使った拡張には向きません。振る舞いの差し替えが必要なら、インスタンスメソッド+インターフェイスを選びます。
interface Formatter { String format(String s); }
class Upper implements Formatter { public String format(String s) { return s.toUpperCase(); } }
Java乱用で設計が硬直化
何でも static にすると、グローバル関数だらけになりオブジェクト指向の恩恵(拡張性・差し替え・状態封装)を失います。「状態に触れない純粋処理」だけ static、それ以外はインスタンスに寄せるのがバランスです。
実用例で身につける
例 1: 検証と変換を static で
public class Validators {
public static boolean isEmail(String s) {
return s != null && s.contains("@") && s.indexOf('@') > 0;
}
public static String normalizeName(String s) {
if (s == null) return "";
return s.trim().toLowerCase();
}
}
Java例 2: 数学ユーティリティ
public final class MathX {
private MathX() {}
public static int clamp(int v, int min, int max) {
if (min > max) throw new IllegalArgumentException("min<=max");
return (v < min) ? min : (v > max) ? max : v;
}
}
Java例 3: main から static を組み合わせて呼ぶ
public class App {
public static void main(String[] args) {
String raw = (args.length > 0) ? args[0] : " Java ";
String name = Validators.normalizeName(raw);
boolean ok = Validators.isEmail("a@b");
System.out.println(name + " / emailOK=" + ok);
}
}
Java設計の指針(重要部分のまとめ)
- static メソッドは「インスタンス不要・状態に触れない純粋処理」に最適。入力→出力を明確化する。
- ユーティリティは final+private コンストラクタで集約し、グローバル状態(static フィールド)への依存を最小化する。
- ポリモーフィズムや差し替えが必要な設計には向かない。拡張性が必要ならインスタンスメソッドとインターフェイスへ寄せる。
- テスト容易性が高いのが利点。副作用を排して、並行実行でも安全な「関数」として設計する。
- main は static。起動処理は静的メソッドに分離して、読みやすく再利用しやすい構成にする。
