static

staic修飾子は、クラスフィールドの定義、クラスメソッドの定義、固定値の定義に利用されます。
staticは、クラス内で定義された場合にインスタンスが幾つ生成されてもstaticで宣言されたフィールド、メソッド、固定値は
それそれ1つしかJVM上に存在しません。

static フィールドのサンプル

StaticSample.java
package jp.co.yourcompany.education.samples;

public class StaticSample {

    /**
     * 生成されたインスタンスのカウント
     */
    private static int staticCount = 0;

    /**
     * 違いがわかるようにstaticでないカウント
     */
    private int count = 0;


    /**
     * デフォルトコンストラクタ
     */
    public StaticSample(){
        staticIncrement();
        increment();
    }

    /**
     * staticカウントのインクリメント
     */
    public void staticIncrement(){
        staticCount++;
    }

    /**
     * カウントのインクリメント
     */
    public void increment(){
        count++;
    }

    /**
     * staticカウンターの取得
     * @return staticCount
     */
    public int getStaticCount(){
        return staticCount;
    }


    /**
     * カウンターの取得
     * @return count
     */
    public int getCount(){
        return count;
    }

    /**
     * javaコマンドから実行されるmainメソッド
     * @param args 引数不要
     */
    public static final void main( String[] args ){

        StaticSample sample1 = new StaticSample();
        System.out.println("sample1.staticCounter:" + sample1.getStaticCount() );
        System.out.println("sample2.Counter      :" + sample1.getCount() );

        StaticSample sample2 = new StaticSample();
        System.out.println("sample2.staticCounter:" + sample2.getStaticCount() );
        System.out.println("sample2.Counter      :" + sample2.getCount() );


        System.out.println("incriment counter");
        sample2.staticIncrement();
        sample2.increment();

        System.out.println("sample1.staticCounter:" + sample1.getStaticCount() );
        System.out.println("sample1.Counter      :" + sample1.getCount() );
        System.out.println("sample2.staticCounter:" + sample2.getStaticCount() );
        System.out.println("sample2.Counter      :" + sample2.getCount() );
    }
}
				
出力結果
sample1.staticCounter:1
sample2.Counter      :1
sample2.staticCounter:2
sample2.Counter      :1
incriment counter
sample1.staticCounter:3
sample1.Counter      :1
sample2.staticCounter:3
sample2.Counter      :2
					

出力結果から、staticカウンタは、インスタンス別に実行しても同一クラス内で1つしか存在しないフィールドという事が理解できます。

逆にstaticで無いメンバーフィールドは、インクリメントのメソッドが実行されても他のインスタンスに影響がない事が理解できます。

このようにstaticのメンバーフィールドを可変な変数として利用するのは適していません。

ビジネスシステムで上記のようなstaticフィールドの利用方法は、まず出現しません。

staticサンプル

staticが良く利用されるサンプルを以下に示します。

StaticInitSample.java
package jp.co.yourcompany.education.samples;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class StaticInitSample {

    /**
     * ファイル読み込み時にエラーが100件出たらフォーマットエラーとする
     */
    public static final int LIMIT_FILE_ERROR_COUNT = 100;

    /**
     * システム間連携のファイルの拡張子
     */
    public static String SYSTEM_CONNECT_FILE_EXTENSION = null;

    /**
     * システム間連携のファイルの接頭辞
     */
    public static String SYSTEM_CONNECT_FILE_PREFIX = null;

    static {
        StaticInitSample.init();
    }

    /**
     * 初期化処理
     */
    public static void init(){
        InputStream in = null;
        try {
            in = StaticInitSample.class.getClassLoader().getResourceAsStream("application.properties");
            if (in == null) {
                System.err.println("application.propertiesファイルがクラスパスに存在しません。");
            }
            Properties prop = new Properties();
            prop.load( in );
            SYSTEM_CONNECT_FILE_EXTENSION = prop.getProperty("system.connect.file.extenstion");
            SYSTEM_CONNECT_FILE_PREFIX = prop.getProperty("system.connect.file.prefix");
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if( in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * javaコマンドから実行されるmainメソッド
     * @param args 引数不要
     */
    public static final void main( String[] args ){

        System.out.println("StaticInitSample.LIMIT_FILE_ERROR_COUNT="
                                + StaticInitSample.LIMIT_FILE_ERROR_COUNT );
        System.out.println("StaticInitSample.SYSTEM_CONNECT_FILE_EXTENSION="
                                + StaticInitSample.SYSTEM_CONNECT_FILE_EXTENSION );
        System.out.println("StaticInitSample.SYSTEM_CONNECT_FILE_PREFIX="
                                 + StaticInitSample.SYSTEM_CONNECT_FILE_PREFIX );
    }
}
				
src/resources/application.properties
system.connect.file.extension=.dat
system.connect.file.prefix=EDCN_
					
出力結果
StaticInitSample.LIMIT_FILE_ERROR_COUNT=100
StaticInitSample.SYSTEM_CONNECT_FILE_EXTENSION=.dat
StaticInitSample.SYSTEM_CONNECT_FILE_PREFIX=EDCN_
					

LIMIT_FILE_ERROR_COUNTはstatic修飾子とfinal修飾子が宣言されているので固定値扱いになります。

SYSTEM_CONNECT_FILE_EXTENSION及びSYSTEM_CONNECT_FILE_PREFIXは、static修飾子のみ宣言されているので、変更は可能です。
但し、クラスフィールドでインスタンスが幾つ生成されてもそれぞれ1つずつの実体しかもちません。

static節でクラスが指定(コンストラクタやクラス指定)場合にメソッドやフィールドにアクセスされる前に1度だけ実行されます。
このサンプルでは、クラスパス上に存在するapplication.propertiesに格納したプロパティファイルを読み取り、メンバーフィールドに設定しています。

staicメソッドはクラスメソッドと呼び、インスタンス数に関係なくJVM上では1つだけ存在します。
定型処理や共通ユーティリティ等に利用されます。

static メンバーフィールドは、クラスフィールドと呼びインスタンス数に関係なくJVM上では1つだけ存在します。
その性質から初期値や定数値に利用される事が多いです。

staticは非staicフィールドやメソッドよりインスタンス数に関係無くメモリ領域を増やさない性質がありますが、
本来インスタンス別(非static)に実装すべきものをstaicにしてしまうとバグの原因になります。
取扱いには、十分に気をつけましょう。

全てのサンプルのダウンロードと実行方法

  • java_sample13.zipファイルを「c:¥download¥java¥samples¥」に保存して下さい。
  • java_sample13.zipファイルを「c:¥projects」配下に展開して下さい。
  • コマンドプロンプトを起動して、「sample13jar.bat」を実行して下さい。
  • javac,jar,実行されてdeployディレクトリに「education-main.jar」が生成されます。
  • コマンドプロンプトから「sample13a.bat」を実行して下さい。PolymorphismSampleクラスが実行されます。
  • コマンドプロンプトから「sample13b.bat」を実行して下さい。StaticSampleクラスが実行されます。
  • コマンドプロンプトから「sample13c.bat」を実行して下さい。StaticInitSampleクラスが実行されます。
  • ソースファイルを改修して実行する場合には、毎回「sample13jar.bat」を実行して下さい。
  • Linux,Unix,iOSの方はバッチファイルはお手数ですが作成して下さい。改行コードが「CRLF」の点ご留意ください。