/** * ドメイン非依存URL出力フィルタ * javadrill.tech移行時はwp_options.home/siteurlのみ変更すればよい * * データベースには絶対URL(https://minner.asia)を保持し、 * 表示時に現在のドメイン(home_url())に動的変換する */ function javadrill_make_urls_dynamic($content) { if (empty($content)) { return $content; } // データベース内の絶対URLを現在のhome_url()に置換 $old_url = 'https://minner.asia'; $new_url = untrailingslashit(home_url()); // http版も対応(念のため) $content = str_replace($old_url, $new_url, $content); $content = str_replace('http://minner.asia', $new_url, $content); return $content; } // 投稿本文、ウィジェット、タームの説明、抜粋に適用 add_filter('the_content', 'javadrill_make_urls_dynamic', 20); add_filter('widget_text', 'javadrill_make_urls_dynamic', 20); add_filter('term_description', 'javadrill_make_urls_dynamic', 20); add_filter('get_the_excerpt', 'javadrill_make_urls_dynamic', 20); 解答例 | Javaドリル https://minner.asia 楽々学べるJavaの問題集 Fri, 05 Sep 2025 01:54:38 +0000 ja hourly 1 https://wordpress.org/?v=6.8.3 https://minner.asia/wp-content/uploads/2023/10/cropped-logo-32x32.png 解答例 | Javaドリル https://minner.asia 32 32 104 「static修羅道」 StepFinal 解答例 https://minner.asia/archives/5245 https://minner.asia/archives/5245#respond Wed, 28 May 2025 03:42:36 +0000 http://localhost/?p=5245

Player.java

public class Player {
  // インスタンス変数:プレイヤーの名前
  private String name;

  // インスタンス変数:プレイヤーのスコア
  private int score;

  // クラス変数:全プレイヤーに共通の最高スコア
  private static int highScore = 0;

  // コンストラクタ:名前を初期化、スコアは0のまま
  public Player(String name) {
    this.name = name;
    this.score = 0;
  }

  // スコアを更新し、必要に応じて highScore も更新する
  public void setScore(int newScore) {
    this.score = newScore;

    // 最高スコアを上回っていれば更新
    if (newScore > highScore) {
      highScore = newScore;
    }
  }

  // プレイヤーのスコア情報を出力
  public void display() {
    System.out.println(name + " のスコア: " + score + "(現在の最高スコア: " + highScore + ")");
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    Player p1 = new Player("Alice");
    Player p2 = new Player("Bob");

    p1.setScore(50);
    p1.display(); // Alice のスコア: 50(現在の最高スコア: 50)

    p2.setScore(80);
    p2.display(); // Bob のスコア: 80(現在の最高スコア: 80)

    p1.setScore(100);
    p1.display(); // Alice のスコア: 100(現在の最高スコア: 100)
  }
}

実行結果

Alice のスコア: 50(現在の最高スコア: 50)
Bob のスコア: 80(現在の最高スコア: 80)
Alice のスコア: 100(現在の最高スコア: 100)

解説

この最終ステップでは、「staticと非staticの設計的な使い分け」を統合的に理解します。


score はインスタンス変数(非static)

  • 各プレイヤーが 自分専用のスコア を持っている
  • だから private int score; は非static
  • p1 のスコアと p2 のスコアは完全に独立して存在する

highScore はstatic変数(クラス全体で共有)

  • 「最高スコア」はゲーム全体で1つだけ存在すればいい
  • どのプレイヤーがスコアを更新しても、条件に応じて highScore に反映される

setScore() のロジックに設計の意図を込める

if (newScore > highScore) {
  highScore = newScore;
}
  • この一行が、「全体で共有される記録を管理する」という static の意味と責任を表している
  • static を使うことによって、「設計でコードに意図を刻む」ことができる

まとめ

  • インスタンスごとの情報(name, score)は非staticで持つべき
  • 全体で1つしか存在しない情報(highScore)はstaticで持つべき
  • static を使うかどうかは「値を共有すべきかどうか」で判断する
  • 設計意図をコードに刻む──それがstatic修羅道のゴール

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// 大丈夫。書いたオレも昔つまずいた。だから残してある。

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5245/feed 0
104 「static修羅道」 Step09 解答例 https://minner.asia/archives/5236 https://minner.asia/archives/5236#respond Wed, 28 May 2025 03:35:49 +0000 http://localhost/?p=5236

Document.java

public class Document {
  // 書類のタイトル(インスタンスごとに異なる)
  private String title;

  // 書類のページ数(インスタンスごとに異なる)
  private int pages;

  // 全書類で共有される「合計ページ数」
  private static int totalPages = 0;

  // コンストラクタ:タイトルとページ数を受け取り、合計ページ数に加算
  public Document(String title, int pages) {
    this.title = title;
    this.pages = pages;

    // クラス全体の合計に加算
    totalPages += pages;
  }

  // 書類情報を出力(インスタンスの情報+クラスの統計情報)
  public void printInfo() {
    System.out.println(title + ": " + pages + "ページ(現在の合計: " + totalPages + ")");
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    Document d1 = new Document("書類A", 5);
    Document d2 = new Document("書類B", 3);
    Document d3 = new Document("書類C", 7);

    d1.printInfo();
    d2.printInfo();
    d3.printInfo();
  }
}

実行結果

書類A: 5ページ(現在の合計: 5)
書類B: 3ページ(現在の合計: 8)
書類C: 7ページ(現在の合計: 15)

解説

「個別の情報」と「全体の統計」を使い分ける

この問題の設計には、以下の2種類の情報が存在します:

  • pages:この書類だけのページ数(インスタンス変数)
  • totalPages:すべての書類の合計ページ数(static変数)

それぞれの性質に合わせて、正しいスコープで変数を設計するのがポイントです。


static変数のふるまい

private static int totalPages = 0;

この変数はクラス全体で1つだけ存在し、new Document(...) するたびにページ数が加算されていきます。

つまり、全体の状態(統計情報)を記録する役割を担っているわけです。


インスタンスの役割とstaticの役割を設計で分離する

  • インスタンス変数:そのオブジェクトだけが持つ情報(ページ数、タイトルなど)
  • static変数:クラス全体で共有する情報(合計、IDカウンタ、設定など)

Javaでは、この「責任の切り分け」が static を設計に活かすポイントです。


まとめ

  • static 変数は「全体で共有される情報」の保持に適している
  • インスタンスごとの情報(title, pages)とは設計上の責務が異なる
  • totalPages のような統計的な情報は、クラス単位で管理するべき

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// あとで調べ直すくらいなら、今、読もうぜ。

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5236/feed 0
104 「static修羅道」 Step08 解答例 https://minner.asia/archives/5228 https://minner.asia/archives/5228#respond Wed, 28 May 2025 02:23:53 +0000 http://localhost/?p=5228

間違ったコード(staticメソッドからインスタンス変数へアクセス)

public class User {
  private String name;

  public User(String name) {
    this.name = name;
  }

  // ※ staticをつけてしまうと、nameが使えずコンパイルエラーになる
  public static void greet() {
    System.out.println("Hello, " + name + "!"); // ← name に赤線(エラー)
  }
}

このコードは コンパイルエラー になります。

non-static variable name cannot be referenced from a static context

正しいコード(staticを外す)

public class User {
  private String name;

  public User(String name) {
    this.name = name;
  }

  // 正しいバージョン:インスタンスメソッド
  public void greet() {
    System.out.println("Hello, " + name + "!");
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    User u1 = new User("Alice");
    User u2 = new User("Bob");

    u1.greet();
    u2.greet();
  }
}

実行結果

Hello, Alice!
Hello, Bob!

解説

staticメソッドとは?

  • staticメソッドは クラスに属しており、インスタンスを持たない
  • new しなくても呼び出せる(例:Math.abs())

だからこそ──

public static void greet() {
  System.out.println("Hello, " + name + "!");
}

このように書いても、name の「中身」が存在しない。
staticメソッドには「誰の name か」がわからないからです。


なぜエラーになるのか?

name は以下のように、インスタンスに属するフィールド(非static)です。

private String name;

これを使うには、「そのインスタンス」が必要です。
でも staticメソッドはインスタンスを前提にしていないため、そもそも name を持っていないのです。


解決方法は?

static を外して、インスタンスメソッド(非static)として定義すること。

public void greet() {
  System.out.println("Hello, " + name + "!");
}

これで this.name が使えるようになります。


まとめ

  • staticメソッドは インスタンスなしで使う設計
  • インスタンス変数(非static)は 各オブジェクトが持つ個別の情報
  • staticメソッドからは インスタンス変数にアクセスできない
  • もしアクセスしたいなら、インスタンスメソッドとして書く

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// よくわからんまま進めても、どっかでツケが来る。

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5228/feed 0
104 「static修羅道」 Step07 解答例 https://minner.asia/archives/5219 https://minner.asia/archives/5219#respond Wed, 28 May 2025 02:15:16 +0000 http://localhost/?p=5219

User.java

public class User {
  // クラス全体で共有する「次に割り当てるID」
  private static int nextId = 1;

  // このインスタンスに割り当てられたID(個別)
  private int id;

  // ユーザーの名前(個別)
  private String name;

  // コンストラクタ:Userを生成するたびにIDを自動で付ける
  public User(String name) {
    this.id = nextId;  // 今のnextIdを割り当て
    nextId++;          // 次のインスタンス用に+1しておく
    this.name = name;
  }

  // ユーザー情報を出力
  public void printInfo() {
    System.out.println("[ID: " + id + "] 名前: " + name);
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    User u1 = new User("Alice");
    User u2 = new User("Bob");
    User u3 = new User("Carol");

    u1.printInfo();
    u2.printInfo();
    u3.printInfo();
  }
}

実行結果

[ID: 1] 名前: Alice
[ID: 2] 名前: Bob
[ID: 3] 名前: Carol

解説

この問題では、インスタンスごとに一意なIDを自動付与する方法として
static 変数をカウンタとして使うテクニックを学びました。


staticな nextId とは?

private static int nextId = 1;
  • すべての User インスタンスで 共有されるカウンタ
  • 初期値を 1 にしておき、インスタンスが作られるたびに1つずつ増やす
  • id = nextId; nextId++; によって、一意なIDを順番に割り振ることができる

なぜ id は非staticなのか?

private int id;
  • id はそのインスタンス専用の情報
  • static にしてしまうと、全インスタンスが同じ値を持ってしまう
  • 各インスタンスが 自分だけのID を持つためには、非staticである必要がある

現場でよく使われる設計

このような「ID連番割り振り」は、実際の開発現場でも非常によく使われます。

例:

  • ユーザーID
  • 注文番号
  • セッション番号

いずれも「一意な番号を自動でふる」ために static 変数を活用します。


まとめ

  • static 変数は インスタンス間で共有するカウンタとして使える
  • コンストラクタ内で id = nextId++ とすることで、一意なIDを割り当てられる
  • static と非static の「役割の違い」を、設計として使い分けることが重要

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// 似た問題でまた詰まる未来、見えてるなら止めよう。

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5219/feed 0
104 「static修羅道」 Step06 解答例 https://minner.asia/archives/5210 https://minner.asia/archives/5210#respond Wed, 28 May 2025 02:07:44 +0000 http://localhost/?p=5210

AppConfig.java

import java.time.LocalDateTime;

public class AppConfig {

  // アプリのバージョン(クラス共通で1つ)
  public static String VERSION;

  // デバッグモード(true: ON, false: OFF)
  public static boolean DEBUG_MODE;

  // 読み込まれた時刻
  public static LocalDateTime LOADED_AT;

  // static初期化ブロック:クラスが最初に読み込まれた時に1度だけ実行される
  static {
    VERSION = "1.0.0";
    DEBUG_MODE = true;
    LOADED_AT = LocalDateTime.now(); // 実行時の時刻を記録
  }

  // 設定情報を出力するメソッド(staticなのでインスタンス化不要)
  public static void printConfig() {
    System.out.println("App Config:");
    System.out.println("VERSION: " + VERSION);
    System.out.println("DEBUG_MODE: " + DEBUG_MODE);
    System.out.println("LOADED_AT: " + LOADED_AT);
  }

  // インスタンス化は不要なのでコンストラクタは定義しない
}

Main.java

public class Main {
  public static void main(String[] args) {
    // アプリ設定情報を出力
    AppConfig.printConfig();
  }
}

実行結果(例)

App Config:
VERSION: 1.0.0
DEBUG_MODE: true
LOADED_AT: 2025-05-26T10:15:30.123456

(※ 実行タイミングによって LOADED_AT の値は変わります)


解説

この問題では、static初期化ブロックの特徴と用途を理解します。


static初期化ブロックとは?

static {
  // 初期化処理
}

これは クラスが最初に読み込まれた瞬間に1度だけ実行される 特別なブロックです。

  • コンストラクタと違い、インスタンスを作らなくても実行される
  • 初期値に時間や外部情報を含めるときに便利
  • static変数の複雑な初期化処理 に向いている

static変数と初期化の関係

public static String VERSION;

このように定義された static 変数は、**クラス全体で共有される「設定項目」**のようなものです。

たとえば:

  • VERSION: 固定値(定数でもいい)
  • DEBUG_MODE: 動作モードの切り替えに使える
  • LOADED_AT: 起動時刻など、1回だけ決定するべき値

こういった値を「まとめて」初期化できるのが staticブロックの強みです。


なぜコンストラクタではなく staticブロックなのか?

  • コンストラクタは インスタンスごとに呼ばれる
  • AppConfig のような設定クラスは newしない設計なので、コンストラクタが実行されない
  • それでも「一度だけの初期化」は必要
    → そこで static初期化ブロックを使う

まとめ

  • static {} は クラスが最初にロードされた瞬間に実行される1回限りの処理
  • static 変数の複雑な初期化や外部依存の初期化に適している
  • この仕組みを使えば、newしないクラスでも一度きりの準備ができる

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// ここ、分かると一気にラクになる。マジで。

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5210/feed 0
104 「static修羅道」 Step05 解答例 https://minner.asia/archives/5202 https://minner.asia/archives/5202#respond Wed, 28 May 2025 01:59:38 +0000 http://localhost/?p=5202

StringUtil.java

public class StringUtil {

  // null または空文字列であれば true を返す
  public static boolean isNullOrEmpty(String str) {
    return str == null || str.isEmpty();
  }

  // 先頭1文字を大文字にし、残りをそのまま返す(例: hello → Hello)
  public static String capitalize(String str) {
    if (str == null || str.isEmpty()) {
      return str;  // nullまたは空文字列はそのまま返す
    }

    // substring(0, 1): 先頭1文字
    // substring(1): 2文字目以降
    return str.substring(0, 1).toUpperCase() + str.substring(1);
  }

  // インスタンス化を禁止する private コンストラクタ(ユーティリティクラスの常套パターン)
  private StringUtil() {
    // 何もしない
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    System.out.println("isNullOrEmpty(null): " + StringUtil.isNullOrEmpty(null));
    System.out.println("isNullOrEmpty(\"\"): " + StringUtil.isNullOrEmpty(""));
    System.out.println("isNullOrEmpty(\"hello\"): " + StringUtil.isNullOrEmpty("hello"));
    System.out.println("capitalize(\"hello\"): " + StringUtil.capitalize("hello"));
    System.out.println("capitalize(\"\"): " + StringUtil.capitalize(""));
  }
}

実行結果

isNullOrEmpty(null): true
isNullOrEmpty(""): true
isNullOrEmpty("hello"): false
capitalize("hello"): Hello
capitalize(""): 

解説

この問題では、「状態を持たず、処理だけを提供するクラス」としての
**ユーティリティクラス(ツールクラス)**を設計・実装しました。


🔸 ユーティリティクラスとは?

ユーティリティクラスとは、「インスタンス化せずに使う便利なメソッド集」です。
Java標準ライブラリでも、Math や Collections などがこれに該当します。

特徴:

  • メソッドはすべて static
  • 状態(インスタンス変数)を持たない
  • コンストラクタを private にしてインスタンス化を禁止

isNullOrEmpty メソッドのポイント

return str == null || str.isEmpty();

nullチェックと空文字チェックの両方を一度に行える、よくあるパターンです。
多くのアプリケーションで、入力値チェックとして重宝されます。


capitalize メソッドの注意点

return str.substring(0, 1).toUpperCase() + str.substring(1);
  • 先頭1文字だけを大文字化
  • 残りはそのまま
  • 空文字やnullを受け取ったときの安全対策も実装

なぜ private コンストラクタにするのか?

private StringUtil() {}

この一行で、new StringUtil() を 外部から不可能にできます。
「newしても意味がないクラス」をインスタンス化させないための、安全設計です。


まとめ

  • ユーティリティクラスは 処理だけを持つクラスとして、static メソッドで構成される
  • インスタンス変数を使わないため、new は不要(むしろ禁止すべき)
  • Javaにおける「設計の意図」としての static の使い道が、明確に見えてくる

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// これは「理解してる風」では絶対超えられない壁。

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5202/feed 0
104 「static修羅道」 Step04 解答例 https://minner.asia/archives/5192 https://minner.asia/archives/5192#respond Wed, 28 May 2025 01:44:08 +0000 http://localhost/?p=5192

AppConstants.java

public class AppConstants {

  // アプリケーションで使用される定数は、public static final で定義する

  // サービス名(文字列の定数)
  public static final String SERVICE_NAME = "MyApp";

  // 税率(数値の定数)
  public static final double TAX_RATE = 0.1;

  // 最大ログイン試行回数(整数の定数)
  public static final int MAX_LOGIN_ATTEMPTS = 3;

  // コンストラクタは private にしてインスタンス化を禁止(常套テクニック)
  private AppConstants() {
    // 何もしない
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    // AppConstants は new しなくても使える
    System.out.println("サービス名: " + AppConstants.SERVICE_NAME);
    System.out.println("税率: " + AppConstants.TAX_RATE);
    System.out.println("最大ログイン試行回数: " + AppConstants.MAX_LOGIN_ATTEMPTS);
  }
}

実行結果

サービス名: MyApp
税率: 0.1
最大ログイン試行回数: 3

解説

なぜ定数に public static final を使うのか?

  1. public … 他のクラスからアクセスできるようにするため
  2. static … インスタンスを作らずに使えるようにするため
  3. final … 値を変更不可にするため(定数化)

この3つを組み合わせることで、**「どこからでも読める・1つだけある・変わらない値」**として使えます。


定数名はすべて大文字+アンダースコア(Javaの慣習)

public static final int MAX_LOGIN_ATTEMPTS = 3;
  • Javaでは「定数」は 全大文字+アンダースコア区切りが定番です
  • 値が変更されないことが 名前の見た目から伝わる ため、可読性が高まります

インスタンス化を防ぐテクニック

private AppConstants() {}

このようにコンストラクタを private にすることで、new AppConstants() を禁止できます。
ユーティリティクラスや定数クラスでは常套手段です。


まとめ

  • public static final は定数の三種の神器(アクセス可/共有/不変)
  • 定数は設計上「意味のある値」に名前を与え、意図を明示する
  • AppConstants のような「定数だけをまとめたクラス」は現場でもよく使われる
  • private コンストラクタでインスタンス化を防止するのもプロっぽい技法

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// 不安なまま前に進んでも、いずれ戻される。今だ。

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5192/feed 0
104 「static修羅道」 Step03 解答例 https://minner.asia/archives/5181 https://minner.asia/archives/5181#respond Wed, 28 May 2025 01:34:27 +0000 http://localhost/?p=5181

User.java

public class User {
  // ユーザー名(インスタンス変数)
  private String name;

  // 各ユーザーが何回メッセージを送ったか(インスタンス変数)
  private int messageCount = 0;

  // 全ユーザーで共有されるメッセージ総数(static = クラス変数)
  private static int totalMessageCount = 0;

  // コンストラクタでユーザー名を受け取って初期化
  public User(String name) {
    this.name = name;
  }

  // メッセージ送信時の処理
  public void sendMessage() {
    messageCount++;        // このインスタンス専用のカウントを1増やす
    totalMessageCount++;   // クラス全体で共通のカウントも1増やす

    // 出力(個別の送信回数と、全体の送信回数を両方表示)
    System.out.println(name + " の送信回数: " + messageCount + "(全体: " + totalMessageCount + ")");
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    User u1 = new User("Alice");
    User u2 = new User("Bob");

    u1.sendMessage();  // Alice: 1(全体: 1)
    u2.sendMessage();  // Bob:   1(全体: 2)
    u1.sendMessage();  // Alice: 2(全体: 3)
  }
}

実行結果

Alice の送信回数: 1(全体: 1)
Bob の送信回数: 1(全体: 2)
Alice の送信回数: 2(全体: 3)

解説

この問題では、インスタンス変数と static(クラス)変数の違いを出力で明確に理解します。


インスタンス変数:messageCount

private int messageCount;

これは 各オブジェクトごとに独立して存在する値です。
new User("Alice") と new User("Bob") では、それぞれの messageCount が別々に管理されています。


static変数:totalMessageCount

private static int totalMessageCount;

これは クラス全体で1つしかない変数です。
u1.sendMessage() でも u2.sendMessage() でも、共通の値が更新されます。


出力結果で差を実感

  • Alice の送信回数 は、Alice自身のカウント(messageCount)だけを見ている
  • 全体: の部分は、totalMessageCount なので すべての送信の合計が出てくる

このように、インスタンス変数とstatic変数が同じように見えてまったく違う役割を持っていることが、出力を通して直感的に理解できます。


まとめ

  • インスタンス変数は「それぞれのオブジェクト専用の情報」
  • static変数は「すべてのオブジェクトが共有する情報」
  • static を使うかどうかは、「その情報を共有したいかどうか」で判断する

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// 自分に聞いてみろ。「わかってる」って言い切れる?

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5181/feed 0
104 「static修羅道」 Step02 解答例 https://minner.asia/archives/5173 https://minner.asia/archives/5173#respond Wed, 28 May 2025 01:26:39 +0000 http://localhost/?p=5173

CalcUtil.java

public class CalcUtil {
  // 2つの整数を加算して返すメソッド(クラスメソッド)
  public static int add(int a, int b) {
    return a + b;
  }

  // 2つの整数を減算して返すメソッド(クラスメソッド)
  public static int subtract(int a, int b) {
    return a - b;
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    // staticメソッドなので new しなくても使える
    int sum = CalcUtil.add(10, 3);
    int diff = CalcUtil.subtract(10, 3);

    // 結果を出力
    System.out.println("10 + 3 = " + sum);
    System.out.println("10 - 3 = " + diff);
  }
}

実行結果(出力)

10 + 3 = 13
10 - 3 = 7

解説

この問題では、static メソッドの特徴「インスタンスを生成しなくても使える」という点に注目します。


なぜ static メソッドを使うのか?

このようなメソッドは、**クラスに属する「機能」**です。
add や subtract は、「状態(インスタンス変数)」に依存せず、ただ入力を受けて計算結果を返すだけの処理です。

そのため、わざわざインスタンスを作る意味がありません。

// 間違った例(インスタンス化の意味がない)
CalcUtil util = new CalcUtil();
int result = util.add(1, 2);  // 不自然

正しい呼び出し方

int sum = CalcUtil.add(10, 3);

このように、クラス名.メソッド名() という形で呼び出せるのが static メソッドの利点です。

Javaの Math クラスや Collections クラスもこのように使われています。


ユーティリティクラスとは?

今回の CalcUtil のように、インスタンスを持たずに便利な処理をまとめたクラスを
「ユーティリティクラス」と呼びます。

特徴は:

  • 全てのメソッドが static
  • 状態(インスタンス変数)を持たない
  • 処理のみを提供する

Java標準APIでもよく見られる設計パターンです。


まとめ

  • static メソッドは、インスタンスを作らずに呼び出せる
  • 「状態に依存しない処理」は static メソッドに向いている
  • ユーティリティクラスはすべてのメソッドを static にすることで、「newしない設計」にできる

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// 見た目だけの理解、そろそろ卒業しない?

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5173/feed 0
104 「static修羅道」 Step01 解答例 https://minner.asia/archives/5163 https://minner.asia/archives/5163#respond Wed, 28 May 2025 01:13:48 +0000 http://localhost/?p=5163

User.java

public class User {
  // ユーザー名(これはインスタンスごとに異なるので、非staticで定義)
  private String name;

  // 全ユーザーで共有するログイン回数(staticを使ってクラスに属させる)
  private static int loginCount = 0;

  // コンストラクタでユーザー名を設定する
  public User(String name) {
    this.name = name;
  }

  // ユーザーがログインしたときに呼ばれるメソッド
  public void login() {
    // クラス全体で共有されている loginCount を1つ増やす
    loginCount++;

    // ユーザー名と、全体での累計ログイン回数を出力する
    System.out.println(name + " がログインしました(累計ログイン回数: " + loginCount + ")");
  }
}

Main.java

public class Main {
  public static void main(String[] args) {
    // ユーザーを2人作成
    User u1 = new User("Alice");
    User u2 = new User("Bob");

    // 各ユーザーがログインする
    u1.login();  // 1回目のログイン
    u2.login();  // 2回目のログイン
    u1.login();  // 3回目のログイン
  }
}

出力結果

Alice がログインしました(累計ログイン回数: 1)
Bob がログインしました(累計ログイン回数: 2)
Alice がログインしました(累計ログイン回数: 3)

解説

この問題では、static 変数がインスタンスに属さず、クラス全体で共有されるという性質を体験します。

🔸 staticでない変数(name)

javaCopyEditprivate String name;

これは User の各インスタンスが持つ「自分専用の値」です。
new するたびに別々の name が保持されます。


🔹 staticな変数(loginCount)

javaCopyEditprivate static int loginCount = 0;

この変数は クラス全体で1つだけ存在する共有のカウンタです。
複数のインスタンスがこの変数を使い回します。どのインスタンスから呼び出しても値は共通で、書き換えた内容が全体に反映されます。

つまり:

  • u1.login() で 1 → 2
  • u2.login() で 2 → 3

とカウントアップされるのは、この loginCount がクラスに属しているからです。


なぜ static を使うのか?

このケースでは「ログイン回数を全体で管理したい」という意図があります。
インスタンス(個人)ではなく、全体での状態を保持するなら、static が必要です。

逆に言えば、「この情報は全体で1つだけでいいか?」と考えると、static を使うべきかどうかの判断ができるようになります。


まとめ

  • static 変数は クラスに1つだけ存在する
  • すべてのインスタンスで 共有される
  • 状態や情報を 全体で保持したいときに使う
  • 対して、個別に保持したい情報はインスタンス変数として宣言する

104 ステップアップ問題 「static修羅道」


Just Keep Typing, Baby!では、この「static修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!

// tesh:
// ここ、スルーしても通れる。でも通じなくなるぞ。

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/5163/feed 0