スライドショー

【Java入門】static変数(クラス変数)の使い方

Javaの「static」を使うと、それが含まれるクラスをインスタンス化せずにその変数にアクセスすることができます。

これに対して「static」を使わない変数はそのクラスをインスタンス化しなければ、その変数にはアクセスできません。

この2つの違いによって、それぞれの変数の役割に違いがあるって知ってましたか?この違いを知ってそれぞれを使い分けることができると、コーディングの幅が広がります。

この記事では、static変数について以下の内容で解説していきます。

  • static変数とは
  • static変数の使い方
  • static変数の注意点
  • static変数について、初心者でもわかるようにやさしく解説します!

    >>> いますぐ「static変数の使い方」を知りたい方はこちら

    static変数(クラス変数)とは

    冒頭で述べたように、「static」句を使うとそれが含まれるクラスをインスタンス化せずにその変数にアクセスすることができます。この変数のことを「static変数」と呼びます。

    これに対して「static」句を使わない変数はそのクラスをインスタンス化しなければ、その変数にはアクセスできません。この変数のことを「非static変数」と呼びます。

    「static変数」は「クラス名.」の後に記述しますので「クラス変数」、「非static変数」は「インスタンス名.」の後に記述しますので「インスタンス変数」とも呼ばれます。

    「クラス変数」はクラス内の変数、「インスタンス変数」はインスタンス固有の変数となります。

    つまり、「クラス変数」はそのクラスから作られたインスタンスの全てで共有される変数、「インスタンス変数」はそのインスタンス1個内だけで使われる変数となります。

    ですので、「クラス変数」はグローバル変数、「インスタンス変数」はローカル変数のような使い分けをすることができます。

    Javaのグローバル変数、ローカル変数とは?

    「クラス変数」はグローバル変数、「インスタンス変数」はローカル変数のような使い分けをすることができると述べましたが、Javaでは厳密にいうとグローバル変数はありません。

    グローバル変数といえば、あらゆる場所からアクセスできる変数という意味になるため、あるクラスから作られたインスタンスで共有できる「クラス変数」とは少々意味合いが違いますよね。

    あくまで、「クラス変数」はクラスから作られたインスタンスの全てで共有される意味で、グローバル変数に近い使い方ができるということです。

    ちなみに、ローカル変数1つのメソッド内だけで使われる変数としてJavaにもあります。

    static変数(クラス変数)の使い方

    それではstatic変数(クラス変数)の使い方をみていきましょう。

    宣言について

    static変数(クラス変数)は以下のように宣言します。

    アクセス修飾子(publicなど) static 型名 変数名

    初期化について

    クラス変数の場合、データ型を指定して宣言すると初期値が与えられます。

    その場合の初期値についてまとめました。

  • 整数値系のデータ型:0(ゼロ)
  • float型:0.0f
  • double型:0.0d
  • 文字型:’\u0000′
  • boolean型:false
  • 参照型(String):null
  • なお、インスタンス変数の場合でも同様に初期値が与えられます。

    呼び出し方について

    static変数(クラス変数)の呼び出し方は以下の通りです。

    クラス名.変数名

    クラスのインスタンスを生成せずに、クラス名を使って呼び出します。

    値の取得と受け渡しについて

    static変数(クラス変数)の値の取得や受け渡しは前述のように呼び出すことで可能です。

    サンプルコードで確認しましょう。

    class ClassSample {
        private int val1 = 0; // 非static変数(インスタンス変数)
        private static int val2 = 0; // static変数(クラス変数)
     
        // コンストラクタ クラスがインスタンス化される度に変数に1加算する
        public ClassSample(int val1, int val2) {
            this.val1 += val1;
            ClassSample.val2 += val2; // 「クラス名.変数名」でstatic変数を宣言
        }
     
        // 変数の値を表示
        public void print(){
            System.out.println("val1 = " + val1 + ", val2 = " + val2);
        }
    }
     
    public class Main {
     
        public static void main(String[] args) { 
            for (int i = 0; i < 3; i++){
                ClassSample cs = new ClassSample(1, 1);
                cs.print();
            }
        }
     
    }

    実行結果:

    val1 = 1, val2 = 1
    val1 = 1, val2 = 2
    val1 = 1, val2 = 3

    この例では、Mainクラスのmainメソッド内でClassSampleクラスから3個インスタンスを生成しています。コンストラクタを使ってインスタンス生成の度にメンバ変数のval1とval2の値に1を加算しています。

    val1は「非static変数」ですのでインスタンスが生成される度に0(ゼロ)で初期化されます。コンストラクタを使って1が加算され、3個のどのインスタンスでも値は1となります。

    これに対して、val2は「static変数」ですので、3回インスタンスが生成される度に1ずつ加算されています。

    val1はローカル変数、val2はグローバル変数として役割が違うことをおわかり頂けたかと思います。

    static変数(クラス変数)の注意点

    static変数はグローバル変数として派生生成された全てのインスタンスからアクセスできます。したがって、参照する場合には値が変更されているのが前提として必要に応じて更新取得する必要があります。

    またインターフェース内でstatic変数を用いる場合は、finalと宣言しなくても暗黙的にfinalとして扱われ定数扱いとなるので注意しましょう。

    こちらもサンプルコードで確認しておきます。

    // インターフェース
    interface InterfaceSample {
        static int Val1 = 0; // 暗黙的にfinal 定数扱い
        default void print(){};
    }
     
    // 親クラス
    abstract class ClassExtends {
        protected static int val2 = 0; // static変数(クラス変数)
        abstract void setVal2(int val2);
    }
     
    // 継承クラス
    class ClassSample extends ClassExtends implements InterfaceSample{
        // コンストラクタ クラスがインスタンス化される度に変数に1加算する
        public ClassSample(int val2) {
            ClassExtends.val2 += val2;
        }
     
        // 変数の値を表示
        public void print(){
            System.out.println("Val1 = " + Val1 + ", val2 = " + val2);
        }
     
        // val2のsetterメソッド
        public void setVal2(int val2){
            ClassSample.val2 = val2;
        }
    }
     
    public class Main {
    
        public static void main(String[] args) {
     
            ClassSample cs1 = new ClassSample(1);
            cs1.print();
            ClassSample cs2 = new ClassSample(1);
            cs2.print();
            ClassSample cs3 = new ClassSample(1);
            cs3.print();
     
            ClassSample cs4 = new ClassSample(1);
            cs4.setVal2(0); // 代入初期化
            cs3.print();
        }
     
    }

    実行結果:

    Val1 = 0, val2 = 1
    Val1 = 0, val2 = 2
    Val1 = 0, val2 = 3
    Val1 = 0, val2 = 0

    このサンプルコードでは、InterfaceSampleインターフェース内でstatic変数Val1を定義し「final」句を付けていませんが、暗黙的finalで定数扱いとなり値を変更することはできません。

    InterfaceSampleインターフェースを実装し、ClassExtendsクラスを継承したClassSampleクラスをMainクラスのmainメソッド内で複数インスタンス化しています。

    ClassSampleクラスのインスタンスからsetVal2メソッドを使用してstatic変数val2の値を代入初期化しています。代入前のcs3インスタンスではval2の値は「3」でしたが、代入後は代入値の「0」(ゼロ)に更新されています。

    static変数val2はClassSampleクラス内では定義せず親クラスのClassExtendsクラスで定義していますので、どこで値が変更されているかは注意する必要があります。

    static変数(クラス変数)の使い方まとめ

    ここでは、紹介したstatic変数の使い方を簡単にまとめています。

    static変数の宣言:

    アクセス修飾子(publicなど) static 型名 変数名

    static変数の呼び出し方:

    クラス名.変数名

    サンプルプログラム(非static変数)の場合:

    class ClassSample {
        private int val = 0;
     
        public ClassSample(int val) {
            this.val += val;
        }
     
        // 変数の値を表示
        public void print(){
            System.out.println("val = " + val);
        }
    }
     
    public class Main {
     
        public static void main(String[] args) { 
            for (int i = 0; i < 3; i++){
                ClassSample cs = new ClassSample(1);
                cs.print();
            }
        }
     
    }
    val = 1
    val = 1
    val = 1

    このように「非static変数」の場合はインスタンスが生成される度に0(ゼロ)で初期化されてしまうため、変数の値は変わりません。

    続いて「static変数」のプログラムを見てみましょう。サンプルプログラム(static変数)の場合:

    class ClassSample {
        private static int val = 0;
     
        public ClassSample(int val) {
            ClassSample.val += val;
        }
     
        // 変数の値を表示
        public void print(){
            System.out.println("val = " + val);
        }
    }
     
    public class Main {
     
        public static void main(String[] args) { 
            for (int i = 0; i < 3; i++){
                ClassSample cs = new ClassSample(1);
                cs.print();
            }
        }
     
    }
    val = 1
    val = 2
    val = 3

    「static変数」の場合は3回インスタンスが生成される度に1ずつ加算されています。

    まとめ

    ここでは、static変数について使い方や使う上での注意点について説明しました。

    「static」句を使い分けることで、ローカル変数、グローバル変数、グローバル定数などを使い分けることができて便利です。

    変数の使い分けを理解していなければ、思わぬ値が出力されるということにもなりかねません。慣れて使いこなすことができるように、この記事を何度も参考にして下さいね!

    LINEで送る
    Pocket

    無料でSEからWebエンジニアへ転職しませんか?



    侍エンジニア塾では、完全未経験の方から現在SEだけどプログラミングはやっていないという経験者まで、幅広い方々の人生を好転させるプログラミング指導を行ってきました。SEの方とお話していくなかで、

    • システムエンジニアという職業だけどコードが書けない
    • 事務作業が多くスキルがないため将来が不安
    • スクールに通うと完全未経験者と同じスタートになるからレベルが合わない
    という、すでに知識があるSEならではのお悩みがあることに気づきました。そんな方におすすめなのが、弊社の「転職コース 」です。

    弊社では、マンツーマンでレッスンを行いますので、現在お持ちの知識レベルからカリキュラムを作成いたします。さらにこちらの転職コースは無料で受講を始められて転職成功でそのまま卒業できるというとてもお得なコースとなっています。

    既に知識のあるSEといっても転職は年齢が若いほど受かりやすいため、まずは無料体験レッスンで今の現状や理想の働き方について一緒に考えていきましょう。

    まずは無料体験レッスンを予約する

    書いた人

    長野 透

    長野 透

    熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
    お問合せはこちらでも受け付けています。
    [email protected]

    おすすめコンテンツ

    あなたにぴったりなプログラミング学習プランを無料で診断!

    プログラミング学習の効率を劇的に上げる学習メソッドを解説