staticメンバーのコードトレース

staticメンバーは各インスタンスではなくクラスに属します。共有カウンタや補助計算を例に、インスタンスメンバーとの格納場所・呼出し方・利用できる名前の違いを理解します。

この単元で学ぶこと

  • staticフィールドとインスタンスフィールドを区別する
  • staticメソッドからアクセス可能な対象を判定する
  • クラス初期化と実体生成の回数を追う

本文解説

生成数を共有する static int count;Counter(){count++;}ならnewを二回行うとcountは2です。Counter b=aという参照代入ではコンストラクタを呼ばずcountは増えません。共有フィールドを生成イベントの記録に使う基本例です。

共有値と個別初期値の関係 static int next;int id=++next;なら最初の実体idは1、二つ目は2です。idは生成時の値をコピーした個別フィールドで、後のnext更新に連動しません。staticを読んで初期化してもid自身がstaticになるわけではありません。

クラス初期化の順序 static int a=2;static int b=a+3;ならbは5です。static初期化ブロックも宣言順に実行されます。static int n=1;static{n+=2;}なら初期化後3です。新しい実体のたびにこの処理を繰返しません。

通常のアクセスと初期化 ここでは独立したJava実行を前提に、static非定数フィールドの使用やインスタンス生成でクラス初期化が必要になる例を扱います。static final定数にはコンパイル時定数として取り込まれる場合があるため、すべてのフィールド参照が必ず同じ初期化順になると一般化しません。

null変数経由のstatic Counter c=null;System.out.print(c.total);でもtotalがstaticならクラスの値を読みます。インスタンスを参照解除しないためnull例外にはなりません。ただし紛らわしい書き方なのでCounter.totalを使います。同じc.localが非staticなら例外です。

staticメソッドとアクセス修飾子 staticでもprivateなら別トップレベルクラスから呼べません。staticは実体に属するかを決め、public/privateはアクセスできる場所を決めます。この二つの修飾子は別の観点です。

参照型のstatic final static final int[] A={1,2};は参照を再代入できませんがA[0]=9は可能です。共有の配列内容を変更すればどの場所から読んでも変更後の値です。不変のデータを設計したいならfinalだけで十分とは限りません。

戻り値と共有値の更新 static int next(){return ++count;}は呼出しごとに共有値を増やして返します。呼出し結果をローカル変数へ代入した後で再度nextを呼んでも、前のローカル値は変わりません。共有状態と値コピーの二段階で追跡します。

図解

共有値と個別値
クラス名で共有値を扱うと、インスタンス変数との違いが明確になる。

重要ポイント

  • staticフィールドは同じ実行内のそのクラスで共有する。
  • クラス名.メンバー名でアクセスできる。
  • staticメソッドにはthisがない。
  • インスタンスを指定すればstaticメソッドからもその状態を使える。

間違えやすい点

  • newの回数だけstaticフィールドを作ると思わない。
  • staticメソッドから非staticメンバーを無条件に呼べると思わない。
  • 変数名経由のstaticアクセスをインスタンス状態と混同しない。

用語解説

クラス変数
staticフィールド。各実体ではなくクラスに属する変数。
クラスメソッド
staticメソッド。特定の受け手を必要としないメソッド。
クラス初期化
staticフィールド初期化子やstatic初期化ブロック等を実行する処理。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。