main()メソッドでも利用されているstaticについての説明ページです。
staticはフィールドやメソッドに付加しますが、staticを付加すると様々な制約なども出てきますので注意が必要です。
staticはインタフェースと同様にイメージがしずらいものの一つです。特徴がすぐに理解できない場合は文法などから覚えるのも学習方法の一つです。
もくじ
staticの概要
staticは前述のように、フィールドとメソッドに付加できます。
staticを単純に説明すると「staticを付加するとインスタンス生成しなくてもフィールドとメソッドが利用できる」ようになります。
Javaでは原則としてクラスからインスタンスを生成し、フィールドやメソッドのメンバにアクセスします。その、原則を変えてしまうのがstaticです。便利なように見えますが、staticを利用することによる弊害もある為、安易にstaticは利用しないようにしましょう。
staticの記述箇所
staticは以下のようにしてフィールドやメソッドに設定します。
staticフィールド | アクセス修飾子 static 型 フィールド名 ; |
---|---|
記述例 | public static double number = 300 ; |
staticメソッド | アクセス修飾子 static 戻り値の型 メソッド名(引数)( |
---|---|
記述例 | public static void execute(){ |
メソッドとフィールド共に、staticは型(もしくは戻り値の型)の左に記述します。型(戻り値の型)の右に記述するとエラーとなりますので注意しましょう。
※アクセス修飾子とstaticの位置は入れ替えが可能です
エラーの例:public void static method() , public int static number
staticなフィールドやメソッドへのアクセス
static付きのフィールドやメソッドにアクセスする際には以下のように記述します。
staticフィールドへのアクセス | クラス名.フィールド名 |
---|---|
記述例 | int tmp = StaticTest.number ; |
staticメソッドへのアクセス | クラス名.メソッド名(引数) |
---|---|
記述例 | StaticTest.execute() ; |
static サンプルプログラム
以下のプログラムを「StaticTest.java」「Number40.java」という名前でWorkフォルダ内に保存します。
保存が完了したら、コマンドプロンプトを起動し、Number40.javaをコンパイルしてみましょう。
1 2 3 4 5 6 7 8 9 |
class StaticTest{ //staticフィールド public static int number ; //staticメソッド public static void execute(){ System.out.println(number + "を表示"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class Number40{ public static void main(String[] args){ //staticなフィールドとメソッドを利用 StaticTest.number = 10000; StaticTest.execute(); //StaticTestをインスタンス生成 StaticTest st = new StaticTest(); StaticTest st2 = new StaticTest(); st.number = 5000; st2.number = 30; st.execute(); st2.execute(); } } |
実行例
C:\work>javac Number40.java
C:\work>java Number40
10000を表示
30を表示
30を表示
※実行例はコンパイルおよび実行時の例を表示しています。
staticの特徴
クラスはインスタンスを生成して、インスタンス毎にフィールドやメソッドを利用できます。しかし、staticを利用するとインスタンス生成を行わなくてもフィールドやメソッドが利用できます。
Number40.javaでは以下のように、staticフィールドやメソッドを利用しています。
1 2 3 |
//staticなフィールドとメソッドを利用 StaticTest.number = 10000; StaticTest.execute(); |
numberフィールドに10000を代入して、execute()メソッドを呼び出すと、numberの値が「10000を表示」という形で表示されます。
しかし、この行以降のプログラムである問題が発生しています。
1 2 3 4 5 6 7 8 |
StaticTest st = new StaticTest(); StaticTest st2 = new StaticTest(); st.number = 5000; st2.number = 30; st.execute(); //30が表示される st2.execute(); //30が表示される |
stインスタンスのnumberフィールド、st2インスタンスのnumberフィールド共に30という同一の数値がexecute()メソッドで表示されてしまいます。
staticを付けたフィールドとメソッドは、インスタンスを生成せずにクラスのフィールドやメソッドとして利用します。以下は図解での説明です。
図解を要約すると、static付きのメンバはクラスに属するものとなり、インスタンスごとのメンバとしては利用できなくなります。
このことからそれぞれのメンバは以下のような特徴があります。
- staticなしのメンバはクラス自体では利用できない
- staticなしのメンバはインスタンスごとにの値を持つことが可能
- staticありのメンバはインスタンス生成せずにクラス自体で利用できる
- staticありのメンバはインスタンスでも利用できるが、インスタンスごとの値をもつことはできない
- staticありのメソッド内からstaticなしのメンバは参照できない
- staticなしのメソッド内からstaticありのメンバは参照できる
staticを付加する意味
クラスに属するということはインスタンスごとに値が持てなくなりますが、それがメリットでもありデメリットでもあります。
そもそもクラスという型からインスタンスという実体を生成して、さらに、状態であるフィールドと操作であるメソッドをインスタンス毎に利用するのが基本となります。
クラスに属するということはインスタンスを作るメリットがなくなります。なぜこのような回りくどい説明になっているかというと、インスタンス生成が面倒だからstaticを付けたということは避けるべきだからです。
では、どのようなときにstaticを付けるかというとフィールドとメソッドによって若干変わります。
- フィールドの場合は「いつも同じ状態を参照できる」
- メソッドの場合は「いつも同じ操作を利用できる」
staticフィールドの代表例は第5章でも説明しますが、MathクラスのPIフィールドです。Math.PIを利用すると円周率が取得できます。staticフィールドは基本的に円周率のように通常変わることのない値となっています。通常変わることのない値の為、finalを併用して定数とすることが多くなります。(例:public static final PI = 3.14 ;)
staticメソッドの代表例はSystem.out.println()やmain()です。staicメソッドはインスタンス生成を必要としないメソッド、つまりインスタンスによって挙動が左右されないメソッドです。System.out.println()のように、よく利用されかつインスタンスごとの操作でなくてもよいメソッドなどに利用されます。
以上のことから、staticフィールドは「静的フィールド」、staticメソッドは「静的メソッド」とも呼ばれます。
staticによる制限
最大のデメリットはわかりづらくなることです。static自体の特徴を理解できない場合は安易にstaticを付けるべきではありません。インスタンスごとに状態や操作が行えなくなるので注意して利用しましょう。
また、staticありとなしのメンバが混在する際には以下の特徴(前述と同じ)にも注意しましょう。
- staticありのメンバからstaticなしのメンバは参照できない
- staticなしのメンバからstaticありのメンバは参照できる
インスタンス生成しなくても利用できるstaticありのメンバから、インスタンス生成後に利用するstaticなしのメンバが利用できると矛盾が生じてしまいます。
以下はコンパイルエラーとなるプログラム例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class StaticTest{ //staticフィールド public static int number ; //staticメソッド public static void execute(){ System.out.println(number + "を表示"); test(); //追加(コンパイルエラー) int a = tmp; //追加(コンパイルエラー) } //以下はstaticなしのメンバを追加 int tmp ; void test(){ System.out.println("テスト"); } } |
static 復習問題
- staticの説明として正しいものを選んでください。
- staticの説明として正しいものを選んでください。
- staticを付加する際の正しい記述を選んでください。
- お疲れ様でした。
-
- staticはフィールドのみに付加できる
- staticはメソッドのみに付加できる
- staticはコンストラクタに付加できる
- staticはフィールドとメソッドに付加できる
-
- staticありメソッド内からstaticなしのメソッドを呼び出すことができない
- staticなしメソッド内からstaticありのメソッドを呼び出すことができない
- staticありメソッド内からstaticありのメソッドを呼び出すことができない
- staticなしメソッド内からstaticなしメソッドを呼び出すことができない
-
public void static test(){
public static void test(){
public int static number ;
public int number static ;
まとめ
- staticはメソッドとフィールドに付加できる
- staticを付加するとインスタンス生成しなくてもメンバを利用できる
- static付きのメンバは「クラス名.フィールド名」「クラス名.メソッド名()」のように利用する
- staticを付加するとクラスで共通のメンバとなり、インスタンス別で利用できなくなる
- staticありのメソッド内からstaticなしのメンバは参照できない