static修飾子の詳細


staticは「グローバル」または「静的」を意味し、メンバー変数とメンバーメソッドを修飾したり、静的staticコードブロックを形成したりすることができますが、Java言語にはグローバル変数の概念はありません.
staticによって修飾されたメンバー変数とメンバーメソッドは、クラスの任意のオブジェクトとは独立しています.すなわち、クラス固有のインスタンスに依存せず、クラスのすべてのインスタンスによって共有される.
このクラスがロードされると、Java仮想マシンはクラス名に基づいて実行時のデータ領域のメソッド領域に内定して見つけることができます.したがって、staticオブジェクトは、オブジェクトを参照することなく、任意のオブジェクトが作成される前にアクセスできます.
publicで修飾されたstaticメンバー変数とメンバーメソッドの本質は、クラスのオブジェクト市を宣言すると、static変数のコピーを生成するのではなく、クラスのすべてのインスタンスが同じstatic変数を共有するグローバル変数とグローバルメソッドです.
static変数の前にprivate修飾があり、この変数はクラスの静的コードブロック、またはクラスの他の静的メンバーメソッドで使用できる(もちろん非静的メンバーメソッドでも使用できる)ことを示しますが、他のクラスではクラス名で直接参照できないことが重要です.実際にprivateはアクセス権限制限であり、staticはインスタンス化せずに使用できることを示しており、理解しやすい.staticの前に他のアクセス権キーを付ける効果も同様です.
static修飾のメンバー変数とメンバーメソッドは、通常、静的変数と静的メソッドと呼ばれ、クラス名で直接アクセスできます.アクセス構文は次のとおりです.
类名静的メソッド名(パラメータリスト...)
类名静的変数名
 
スタティックで修飾されたコードブロックは静的コードブロックを表し、Java仮想マシン(JVM)がクラスをロードすると、そのコードブロックが実行され、非常に役に立ちます.
1、static変数
静的かどうかによってクラスメンバー変数を分類するには、staticによって修飾された変数、静的変数またはクラス変数と呼ばれ、staticメンバー変数の初期化順序は定義された順序で初期化される.もう1つはstaticによって修飾されていない変数で、インスタンス変数と呼ばれます.
両者の違いは次のとおりです.
静的変数がメモリに1つしかコピーされていない(メモリを節約する)場合、JVMは静的にメモリを1回だけ割り当て、クラスをロードする過程で静的変数のメモリ割り当てを完了し、クラス名で直接アクセス(便利)することができ、もちろんオブジェクトでアクセスすることもできます(ただし、これは推奨されません).
インスタンス変数の場合、インスタンスを作成するたびに、インスタンス変数にメモリが割り当てられます.インスタンス変数は、メモリに複数のコピーがあり、互いに影響しません(柔軟です).
 
通常、静的変数は、次の2つの機能を実装する必要がある場合に使用されます.
(1)オブジェクト間で値を共有する場合
(2)変数にアクセスしやすい場合
2、静的方法
静的メソッドはクラス名で直接呼び出すことができ、任意のインスタンスも呼び出すことができるため、静的メソッドではthisとsuperキーを使用することはできません.所属するクラスのインスタンス変数とインスタンスメソッド(staticを持たないメンバー変数とメンバーメソッド)に直接アクセスすることはできません.所属するクラスの静的メンバー変数とメンバーメソッドにのみアクセスできます.インスタンスメンバーが特定のオブジェクトに関連付けられているためです.ただし、静的メソッドでは非静的メンバーメソッドおよび非静的メンバー変数にアクセスできませんが、非静的メンバーメソッドでは静的メンバーメソッド/変数にアクセスできます.
staticメソッドは任意のインスタンスとは独立しているため、抽象的なabstractではなくstaticメソッドを実装する必要があります.
例えば、メソッドの呼び出しを容易にするために、Java APIのMathクラスのすべてのメソッドは静的であり、一般的なクラス内部のstaticメソッドも他のクラスの呼び出しを容易にする.
静的メソッドはクラス内部の特殊なメソッドであり、必要に応じて対応するメソッドを静的に宣言するだけで、クラス内部のメソッドは一般的に非静的である.
したがって、オブジェクトを作成せずにメソッドを呼び出したい場合はstaticに設定できます.私たちが最もよく見られるstaticメソッドはmainメソッドですが、なぜmainメソッドがstaticでなければならないのかは、今ではよく分かります.プログラムはmainメソッドを実行するときにオブジェクトを作成しないため、クラス名でのみアクセスできます.
また、staticとして表示されなくても、クラスのコンストラクタは実際には静的な方法であることを覚えておいてください.
3、staticコードブロック
staticコードブロックは静的コードブロックとも呼ばれ、クラスの中でクラスメンバーとは独立したstatic文ブロックであり、複数あってもよいし、位置は任意に置くことができ、それはいかなる方法の体内にもなく、JVMがクラスをロードする時にこれらの静的コードブロックを実行し、staticコードブロックが複数ある場合、JVMはそれらがクラスに現れる順番にそれらを実行する.各コードブロックは1回のみ実行されます.
staticキーワードのもう一つの重要な役割は、プログラムのパフォーマンスを最適化するために静的コードブロックを形成することです.
なぜstaticブロックがプログラムのパフォーマンスを最適化できるのかは、クラスのロード時に一度しか実行されないという特性のためです.次に例を示します.
class Person{
    private Date birthDate;
    
    public Person(Date birthDate) {
        this.birthDate = birthDate;
    }
    
    boolean isBornBoomer() {
        Date startDate =Date.valueOf("1946");
        Date endDate =Date.valueOf("1964");
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

isBornBoomerはこの人が1946-1964年に生まれたかどうかについて使用されていますが、isBornBoomerが呼び出されるたびにstartDateとbirthDateの2つのオブジェクトが生成され、空間の浪費をもたらし、このような効率に変更すればより良いです.
class Person{
    private Date birthDate;
    private static Date startDate,endDate;
    static{
        startDate =Date.valueOf("1946");
        endDate =Date.valueOf("1964");
    }
    
    public Person(Date birthDate) {
        this.birthDate = birthDate;
    }
    
    boolean isBornBoomer() {
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate)< 0;
    }
}

したがって、一度だけ行う初期化操作の一部をstaticコードブロックに配置して行うことが多い.
4、final static
static finalは、メンバー変数とメンバーメソッドを修飾するために使用され、「グローバル定数」と簡単に理解できます.
変数の場合、値が与えられると変更できず、クラス名でアクセスできることを示します.
メソッドの場合は、上書きできないことを示し、クラス名で直接アクセスできます.
staticとfinalで修飾されたインスタンス定数では、インスタンス自体は変更できませんが、ArrayList、HashMapなどのコンテナタイプのインスタンス変数では、コンテナ変数自体を変更することはできませんが、コンテナに格納されているオブジェクトを変更することができます.
public class TestStaticFinal {
        private static final StringstrStaticFinalVar = "aaa";
        private static String strStaticVar =null;
        private final String strFinalVar =null;
        private static final intintStaticFinalVar = 0;
        private static final IntegerintegerStaticFinalVar = new Integer(8);
        private static final ArrayList<String> alStaticFinalVar = new ArrayList<String>();
 
        private void test() {
              
 
                strStaticFinalVar="    ";  //  ,final    ,         .
                strStaticVar = "    ";       //  ,static     ,     .
                strFinalVar="    ";        //  , final    ,          (    null),           。
                intStaticFinalVar=2;           //  , final    ,          (    null),           。
                integerStaticFinalVar=newInteger(8);  //  , final    ,          (    null),           。
                alStaticFinalVar.add("aaa");      //  ,          ,          。          ,     。
                alStaticFinalVar.add("bbb");      //  ,          ,          。          ,     。
               
        } 

5、実行順序
スタティックコードブロック、スタティックメソッド、構築メソッドなど、クラスのロード、インスタンス化時の実行順序はどのようなものですか?次の例で検証します.この2つのクラスがあります.
class Father{
     
      static int a = before();
            
      static{
             System.out.println("Fatherstatic");
      }
     
      static int b = after();
     
      public Father(){
             System.out.println("Fatherconstructor");
      }
     
     
      static int before(){
             System.out.println("Fatherstatic before");
             return 1;
      }
     
      static int after(){
             System.out.println("Fatherstatic after");
             return 2;
      }
}
 
class Son extends Father{
     
      int a = fun();
      int b = fun2();
      static{
             System.out.println("Sonstatic");
      }
     
      public Son(){
             System.out.println("Sonconstructor");
      }
     
      static int fun(){
             System.out.println("Son staticfunction");
             return 1;
      }
     
      int fun2(){
             System.out.println("Sonnon-static function");
             return 1;
      }
}

 
次のコードでテストします.
Class s =Class.forName("Son");
印刷結果は次のとおりです.
Father staticbefore
Father static
Father staticafter
Son static
 
Class.forNameは、クラスをJVMにロードします.サブクラスをロードする前に、親クラスをロードし、呼び出しがある場合は、表示される順序で静的コードブロック、静的メソッドを実行する必要があります.
 
次のコードテストに変更します.
Son son = newSon();
印刷結果は次のとおりです.
Father staticbefore
Father static
Father staticafter
Son static
Fatherconstructor
Son staticfunction
Son non-staticfunction
Son constructor
 
上のコードは直接Sonをインスタンス化し、Classファイルを仮想マシンにロードする必要があるため、前の4行の印刷結果は前の例と同じです.
コードの実行順序は、静的コードを先に実行し、構造方法を実行することである.親クラスを先に実行し、子クラスを実行します.