JAvaにおけるstaticの理解(転載)

20843 ワード

static修飾子を使用して修飾されたプロパティ(メンバー変数)、定数、およびメンバーメソッドを静的変数、定数、メソッドと呼び、総称して
静的メンバーは、クラス全体に属し、クラスの特定のインスタンスに依存せず、クラスのすべてのインスタンスによって共有されます.このクラスがロードされる限り、Java仮想マシンはクラス名に基づいてランタイムデータ領域のメソッド領域内でそれらを見つけることができます.
静的メンバーを呼び出す構文は次のとおりです.
  .    

せいてきへんすう
実際のクラスのメンバー変数は、staticによって修飾されたメンバー変数を指す静的変数(またはクラス変数と呼ばれる)と、staticによって修飾されていないメンバー変数を指すインスタンス変数の2つに分けることができます.
静的変数とインスタンス変数の違いは次のとおりです.
  • 静的変数の場合、実行時にJava仮想マシンは静的変数に1回だけメモリを割り当て、クラスをロードする過程で静的変数のメモリ割り当てを完了します.クラスの内部では、任意の方法で静的変数に直接アクセスできます.他のクラスでは、クラス名でクラス内の静的変数にアクセスできます.
  • インスタンス変数の場合、Java仮想マシンはインスタンス変数を作成するたびに、インスタンス変数にメモリを割り当てます.クラスの内部では、非静的メソッドでインスタンス変数に直接アクセスできます.このクラスの静的メソッドまたは他のクラスでは、クラスのインスタンスオブジェクトからアクセスする必要があります.

  • クラスにおける静的変数の役割は次のとおりです.
  • 静的変数はクラスのすべてのインスタンスによって共有され得るので、静的変数はインスタンス間の共有データとして使用され、インスタンス間の相互作用性を増加させることができる.
  • クラスのすべてのインスタンスに同じ定数属性が含まれている場合、この属性を静的定数タイプとして定義することで、メモリ領域を節約できます.たとえば、クラスに静的定数PIを定義します.
  •        
    
           
           
           
           
    1. public static double PI=3.14159256;
    public static double PI=3.14159256;

    例1静的変数付きクラスを作成しmain()メソッドで変数にアクセスし、結果を出力します.
           
    
           
           
           
           
    1. public class StaticVar
    2. {
    3. public static String str1="Hello";
    4. public static void main(String[] args)
    5. {
    6. String str2="World!";
    7. // str1
    8. String accessVar1=str1+str2;
    9. System.out.println(" 1 , :"+accessVar1);
    10. // str1
    11. String accessVar2=StaticVar.str1+str2;
    12. System.out.println(" 2 , :"+accessVar2);
    13. // svt1 str1
    14. StaticVar svt1=new StaticVar();
    15. svt1.str1=svt1.str1+str2;
    16. String accessVar3=svt1.str1;
    17. System.out.println(" 3 , :"+accessVar3);
    18. // svt2 str1
    19. StaticVar svt2=new StaticVar();
    20. String accessVar4=svt2.str1+str2;
    21. System.out.println(" 4 , :"+accessVar4);
    22. }
    23. }
    public class StaticVar
    {
        public static String str1="Hello";
        public static void main(String[] args)
        {
            String str2="World!";
            //    str1
            String accessVar1=str1+str2;
            System.out.println("  1        ,   :"+accessVar1);
            //      str1
            String accessVar2=StaticVar.str1+str2;
            System.out.println("  2        ,   :"+accessVar2);
            //    svt1  str1
            StaticVar svt1=new StaticVar();
            svt1.str1=svt1.str1+str2;
            String accessVar3=svt1.str1;
            System.out.println(" 3       ,   :"+accessVar3);
            //    svt2  str1
            StaticVar svt2=new StaticVar();
            String accessVar4=svt2.str1+str2;
            System.out.println("  4        ,   :"+accessVar4);
        }
    }

    このプログラムを実行した結果を以下に示します.
      1        ,   :HelloWorld!
      2        ,   :HelloWorld!
      3        ,   :HelloWorld!
      4        ,   :HelloWorld!World!

    実行結果から分かるように、
    クラスに静的属性(メンバー変数)を定義し、main()メソッドで直接アクセスしたり、クラス名でアクセスしたり、クラスのインスタンスオブジェクトでアクセスしたりできます.
    注:静的変数は、複数のインスタンスによって共有されます.
    スタティツクメソッド
    メンバー変数と同様に、メンバーメソッドは静的メソッド(またはクラスメソッドと呼ばれる)とstaticによって修飾されたメンバーメソッドを指し、インスタンスメソッドはstaticによって修飾されていないメンバーメソッドを指す.
    静的メソッドとインスタンスメソッドの違いは次のとおりです.
  • 静的メソッドは、その属するクラスのインスタンスを介して呼び出される必要はありません.したがって、静的メソッドではthisキーワードは使用できません.また、属するクラスのインスタンス変数およびインスタンスメソッドに直接アクセスすることはできませんが、属するクラスの静的変数および静的メソッドに直接アクセスできます.また,thisキーワードと同様にsuperキーワードもクラスの特定のインスタンスに関連するため,静的メソッドではsuperキーワードを使用することはできない.
  • インスタンスメソッドでは、属するクラスの静的変数、静的メソッド、インスタンス変数、およびインスタンスメソッドに直接アクセスできます.

  • 例2静的変数付きクラスを作成し、いくつかの静的メソッドを追加して静的変数の値を変更し、main()メソッドで静的メソッドを呼び出して結果を出力します.
           
    
           
           
           
           
    1. public class StaticMethod
    2. {
    3. public static int count=1; // count
    4. public int method1()
    5. { // method1
    6. count++; // count
    7. System.out.println(" method1() count="+count); // count
    8. return count;
    9. }
    10. public static int method2()
    11. { // method2
    12. count+=count; // count
    13. System.out.println(" method2() count="+count); // count
    14. return count;
    15. }
    16. public static void PrintCount()
    17. { // PrintCount
    18. count+=2;
    19. System.out.println(" PrintCount() count="+count); // count
    20. }
    21. public static void main(String[] args)
    22. {
    23. StaticMethod sft=new StaticMethod();
    24. //
    25. System.out.println("method1() intro1="+sft.method1());
    26. //
    27. System.out.println("method2() intro1="+method2());
    28. // , coimt
    29. StaticMethod.PrintCount();
    30. }
    31. }
    public class StaticMethod
    {
        public static int count=1;    //      count
        public int method1()
        {    //    method1
            count++;    //      count   
            System.out.println("      method1()   count="+count);    //  count
            return count;
        }
        public static int method2()
        {    //    method2
            count+=count;    //      count   
            System.out.println("      method2()   count="+count);    //  count
            return count;
        }
        public static void PrintCount()
        {    //    PrintCount
            count+=2;
            System.out.println("      PrintCount()   count="+count);    //  count
        }
        public static void main(String[] args)
        {
            StaticMethod sft=new StaticMethod();
            //            
            System.out.println("method1()       intro1="+sft.method1());
            //        
            System.out.println("method2()       intro1="+method2());
            //          ,  coimt
            StaticMethod.PrintCount();
        }
    }

    このプログラムを実行した結果を以下に示します.
          method1()   count=2
    method1()       intro1=2
          method2()   count=4
    method2()       intro1=4
          PrintCount()   count=6

    このプログラムでは、静的変数countはインスタンス間の共有データとして機能するため、異なる方法でcountを呼び出すと値が異なる.このプログラムから、静的メソッドmethod 1()およびPrintCount()では非静的メソッドmethod 1()を呼び出すことができず、method 1()メソッドでは静的メソッドmethod 2()およびPrintCount()を呼び出すことができることがわかる.
    非静的メソッドにアクセスするには、インスタンスオブジェクトを介してアクセスする必要がありますが、静的メソッドにアクセスする場合は、直接アクセスしたり、クラス名を介してアクセスしたり、オブジェクトをインスタンス化してアクセスしたりすることができます.
    スタティツクコードブロック
    静的コードブロックとは、Javaクラスのstatic{}コードブロックを指し、主にクラスの初期化に使用され、クラスの静的変数に初期値を付与します.静的コードブロックの特徴は次のとおりです.
  • 静的コードブロックは、1つの方法と同様であるが、いずれの方法体にも存在してはならない.
  • Java仮想マシンはクラスをロードするときに静的コードブロックを実行します.クラスに複数の静的コードブロックが含まれている場合、Java仮想マシンはクラスに表示される順序で順次実行され、各静的コードブロックは1回のみ実行されます.
  • 静的コードブロックは、静的メソッドと同様に、クラスのインスタンス変数およびインスタンスメソッドに直接アクセスすることはできず、クラスのインスタンスオブジェクトからアクセスする必要がある.

  • 例3 Javaクラスを記述し、クラスに静的変数を定義し、静的コードブロックを使用して静的変数の値を変更する.最後にmain()メソッドでテストと出力を行います.
           
    
           
           
           
           
    1. public class StaticCode
    2. {
    3. public static int count=0;
    4. {
    5. count++;
    6. System.out.println(" count="+count);
    7. }
    8. static
    9. {
    10. count++;
    11. System.out.println(" count="+count);
    12. }
    13. public static void main(String[] args)
    14. {
    15. System.out.println("*************** StaticCode1 ***************");
    16. StaticCode sct1=new StaticCode();
    17. System.out.println("*************** StaticCode2 ***************");
    18. StaticCode sct2=new StaticCode();
    19. }
    20. }
    public class StaticCode
    {
        public static int count=0;
        {
            count++;
            System.out.println("       count="+count);
        }
        static
        {
            count++;
            System.out.println("      count="+count);
        }
        public static void main(String[] args)
        {
            System.out.println("*************** StaticCode1    ***************");
            StaticCode sct1=new StaticCode();
            System.out.println("*************** StaticCode2    ***************");
            StaticCode sct2=new StaticCode();
        }
    }
    

    上記の例のように、静的コードブロックが一度しか実行されないことを説明するために、比較として非静的コードブロックを追加し、メインメソッドで2つのクラスのインスタンスオブジェクトを作成した.上記の例の実行結果は、次のとおりです.
          count=1
    *************** StaticCode1    ***************
           count=2
    *************** StaticCode2    ***************
           count=3