Java Staticの使い方

7913 ワード

JavaではStaticキーワードが多く使われていますが、要約すると、Static member、Static Block、Static importの3つの部分があります.次に、Static Entry Staticエンティティには、静的変数、静的メソッド、静的内部クラスが含まれます.まずStaticという言葉を理解します.Javaでは、これらのエンティティがすべて分類され、クラスにバインドされ、すべてのクラスのインスタンスがこれらのエンティティを共有することを意味します.例えば同じメーカーが生産した自転車は,自転車を一つのクラスに抽象化し,対象は自転車1台あたりである.自転車ごとに価格や色などの属性があり、これらの属性は自転車ごとに異なりますが、彼らの音場メーカーは同じで、このときメーカーを静的なタイプに定義することができます.Staticエンティティはメモリに単独で格納され、オブジェクトの変数とは格納されません.静的変数:次のように定義します.
private static int VENDOR = 'ABC' ;

一般に,静的変数を大文字で表し,複数の単語がある場合は下線で区切る.静的変数もクラス変数となり、名前の通り、これらの変数はインスタンスオブジェクトではなくクラスに属します.特定のクラス・ローダには、複数のオブジェクトを作成しても、オブジェクトを作成してもいない静的変数が1つしか存在しません.私の前提に注意してください.特定のクラス・ローダ、すなわち、異なるクラス・ローダには複数の教壇変数がある可能性があります.静的変数にアクセスする場合は、クラスから直接アクセスできます:ClassName.VENDOR.もちろんインスタンスからアクセスできますが、「静的」という文字が表示されないため、推奨されません.では、静的変数を宣言できる場所はどこですか?一般的なクラスでは、クラスで直接宣言(メソッドと並べて)できます.メソッドが静的であるかどうかにかかわらず、メソッドで静的変数を宣言することはできません.内部クラスでは、状況が異なり、非静的内部クラスでは静的変数を宣言できません(実際には、非静的内部クラスでは静的試行エンティティを宣言できません).静的内部では、静的変数を宣言できます.静的変数は、外部クラスまたは静的内部クラスでのみ定義できます.
静的メソッド:フォーマットを次のように定義します.
public static void doSomething() {...

同様に、静的メソッドもクラスのすべてに属しますが、オブジェクトは同様に呼び出すことができます.静的メソッドは一般的に静的変数を操作するために使用され、静的メソッドでは非静的変数を直接参照することはできません.非静的変数はインスタンスの所有であるため、オブジェクトがまだ作成されていない場合はインスタンス変数が存在しません.どのように参照しますか?非静的変数を参照する場合は、オブジェクトのみで参照できます.静的メソッドではthis、superなどのキーワードは参照できません.最も一般的な静的メソッドはもちろんmain()メソッドです.他のすべてのオブジェクトが作成される前にmainメソッドが呼び出される必要があるため、クラスでのみこのmainメソッドが呼び出されます.mainメソッドでは、非静的変数を直接参照することはできません.
public class StaticMethod {
    private int age = 0 ;
    private static String VENDOR = "JAC";
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        /*
         * doesn't work
         */
        System.out.println(age);
        /**
         * OK
         */
        System.out.println(VENDOR);

    }

}

静的メソッドでは、非静的メソッドを直接呼び出すことはできません.オブジェクト参照のみできます.要約すると、インスタンスメソッドはインスタンス変数、静的変数に直接アクセスでき、インスタンスメソッド、静的メソッドを直接呼び出すことができます.ただし、静的メソッドは静的変数に直接アクセスしたり、静的メソッドを呼び出したりすることしかできません.非静的変数またはメソッドにアクセスするには、オブジェクト参照のみを使用します.例を次に示します.
public class StaticMethod {

    private int age = 0 ;
    private static String VENDOR = "JAC";
    
    public void show() {
        System.out.println("Non-Static");
    }
    
    public static void staticShow() {
        System.out.println("Static");
    }
    
    public static void main(String[] args) {
        //    
        System.out.println(VENDOR); 
        staticShow();
         //      
        StaticMethod staticMethod = new StaticMethod();
        System.out.println(staticMethod.age);
        staticMethod.show();

    }

}

では、静的メソッドはどこで定義できますか?公式説では、Static methods can only be declared in a static or top-level type.つまり、外層のクラスでは、静的メソッドを定義することができる.しかし,内層のクラスでは静的な内部クラスのみが静的メソッドを定義できる.静的変数の場合と同じです.
静的クラスは、内部クラスでのみ静的クラスを定義できます.すなわち,内部クラスには静的と非静的の区別がある.静的内部クラスは、外部クラスのオブジェクトが作成されていなくても、外部クラスにバインドされます.しかし、非静的内部クラスは異なり、特定の外層クラスオブジェクトにバインドされ、外部クラスオブジェクトのみが存在し、内部クラスは存在します.内部静的内のメソッドには静的と非静的の区別があり、静的メソッドの場合、外層では内部静的内で直接呼び出すことができ、非静的メソッドの場合、内部静的クラスのオブジェクトを作成してから呼び出す必要があります.
public class Test{

    public static void main(String[] args) {
        StaticInnerClass.diaplay();
        StaticInnerClass i = new StaticInnerClass();
        i.test();
        
    }
    
    static class StaticInnerClass {
        private static String VENDOR = "JAC";
        private static void diaplay() {
            System.out.println("Inner static class, static method");
        }
        
        private void test() {
            System.out.println("Inner static class,non-static methon");
        }
        
    }

}

非静的内部クラスについては,本稿の検討内容ではなく,参考http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html.静的エンティティの検討はここまでです.
Static Block静的ブロックのフォーマットは以下の通りである:(以下、完全な例であり、次に説明する)
import java.util.HashMap;
import static java.lang.Math.PI;
/**
 * 
 * @author bingduanLin
 *
 */


public class StaticBlock {

    {
        System.out.println("Instance Initializer, run when an object is created! ");
    } // can bu reuser in constructors!!
    
    
    
    private static final HashMap MAP = new HashMap();
    static {
        MAP.put("banana", "honey");
        MAP.put("peanut butter", "jelly");
        MAP.put("rice", "beans");
      }
    static {
        System.out.println("Static Initializer, run when the class is loaded!");
        MAP.put("cons", "cons");
    }
    
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        new StaticBlock();
        new StaticBlock();
        new StaticBlock();
        System.out.println(MAP);
        /**
         * The static import declaration is analogous to the normal import declaration. 
         * Where the normal import declaration imports classes from packages, allowing 
         * them to be used without package qualification, the static import declaration 
         * imports static members from classes, allowing them to be used without
         * class qualification.
         */
        System.out.println(PI);

    }

}

static{}という部分は静的ブロックであり、クラスローダがクラスにロードされると、この部分のコードが実行され、静的変数の初期化作業によく使用されます.もちろん、これらの初期化作業を完了するために静的メソッドを宣言することができ、このような利点は、これらの初期化作業が再び呼び出され、初期化ブロックでは、コードが1回しか実行されず、再呼び出されないことである.静的ブロックでは、静的変数にアクセスし、静的メソッドを呼び出すことができます.staticを削除すると、{}内のコードはクラスオブジェクトを作成するときに実行されます(このコードの一部を各コンストラクション関数にコピーすることに相当します).これにより、ブロック内のコンテンツの複数のコンストラクション関数での多重化が実現されます.上記のコード出力結果は次のとおりです.
Static Initializer, run when the class is loaded!
Instance Initializer, run when an object is created! 
Instance Initializer, run when an object is created! 
Instance Initializer, run when an object is created! 
{banana=honey, rice=beans, peanut butter=jelly, cons=cons}
3.141592653589793

static{}のコードは1回しか実行されず、{}のコードは新しいオブジェクトを作成するたびに実行されることがわかります.{}このようなコードブロックは、コンストラクション関数ブロック(Constructor Block)とも呼ばれる.さらに例を挙げます.
package learn.study;

public class StaticExample{
    static {
        System.out.println("This is first static block");
    }

    public StaticExample(){
        System.out.println("This is constructor");
    }

    public static String staticString = "Static Variable";

    static {
        System.out.println("This is second static block and refer to STATIC VARIABLES:"
                                                + staticString);
    }

    public static void main(String[] args){
        /*StaticExample statEx = new StaticExample();
        StaticExample.staticMethod2();*/
        staticMethod2();
    }

    static {
        System.out.println("This is third static block and refer to STATIC METHOD");
        staticMethod();
    }

    public static void staticMethod() {
        System.out.println("This is static method");
    }

    public static void staticMethod2() {
        System.out.println("This is static method2");
    }
}

出力:
This is first static block
This is second static block and refer to STATIC VARIABLES:Static Variable
This is third static block and refer to STATIC METHOD
This is static method
This is static method2

もちろん、静的ブロックにも限界があります.例えば、静的ブロックコードのサイズがJVMで規定された値を超えてはいけない、this、superキーワードを使ってはいけない、静的ブロックから値を返すことができない、デバッグの難易度を高めるなどです.したがって、静的ブロックに発生する可能性のある異常の処理に注意しなければならない.
静的インポート:最後に静的インポートについて説明します.上のコード:static import java.lang.Math.PIは上の注釈を見て、importの後、Classの前のパッケージ名を省略して直接クラスを使用することができます.例えばSystem.out.println(Math.PI)です.静的インポートの後、クラス名も省略して、クラスの変数や方法、すなわちSystem.out.println(Math.PI)を直接使用することができます.・静的インポートは便利ですが、非常に注意して使用してください.公式文書を参照:http://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html