[Java]静的キーワードの適用と分析

1.静的キーワードの目的

「JavaProgrammingThought」のP86ページにそのような一節があります。

「静的メソッドはこれがないメソッドです。静的メソッド内で非静的メソッドを呼び出すことはできません。その逆も同様です。また、オブジェクトを作成せずにクラス自体からのみ静的メソッドを呼び出すことができます。これは実際には静的メソッドの主な目的。」

この節では、staticメソッドの特別な機能のみを示していますが、staticキーワードの基本的な機能を確認できます。つまり、1文の説明は次のとおりです。

オブジェクトを作成せずに(メソッド/変数)を呼び出すと便利です。

明らかに、staticキーワードによって変更されたメソッドまたは変数は、アクセスするオブジェクトに依存する必要はありません。クラスがロードされている限り、クラス名を介してアクセスできます。

静的を使用して、クラスのメンバーメソッドとメンバー変数を変更できます。さらに、静的コードブロックを記述して、プログラムのパフォーマンスを最適化できます。

1)静的メソッド

静的メソッドは一般に静的メソッドと呼ばれます。静的メソッドはどのオブジェクトにも依存しないため、アクセスできます。静的メソッドの場合、どのオブジェクトにもアタッチされていないため、これはありません。オブジェクトがないため、言及できません。これを。また、この機能により、クラスの非静的メンバー変数および非静的メンバーメソッドに静的メソッドでアクセスすることはできません。非静的メンバーメソッド/変数は、呼び出すことができるように特定のオブジェクトに依存する必要があるためです。

ただし、静的メンバーメソッドおよび非静的メンバー変数は静的メソッドではアクセスできませんが、静的メンバーメソッド/変数は非静的メンバーメソッドでアクセスできることに注意してください。

ここに写真の説明を挿入

2)静的変数

静的変数は静的変数とも呼ばれます。静的変数と非静的変数の違いは、静的変数はすべてのオブジェクトで共有され、メモリ内にコピーが1つしかないことです。これは、クラスが最初にロードされたときにのみ初期化されます。非静的変数はオブジェクトによって所有され、オブジェクトの作成時に初期化されます。複数のコピーがあり、各オブジェクトが所有するコピーは相互に影響しません。

静的メンバー変数の初期化順序は、定義された順序で初期化されます。

3)静的コードブロック

staticキーワードのもう1つの重要な機能は、静的コードブロックを形成して、プログラムのパフォーマンスを最適化することです。静的ブロックはクラスのどこにでも配置でき、クラスには複数の静的ブロックが存在する可能性があります。クラスが最初にロードされるとき、各静的ブロックは静的ブロックの順序で実行され、1回だけ実行されます。

静的コードブロック機能の概要:

  • このクラスを初めて使用する場合、静的コードブロックは1回だけ実行されます。
  • 静的コンテンツは常に非静的コンテンツよりも優先されるため、静的コードブロックは構築メソッドの前に実行されます。
  • 静的コードブロックの一般的な使用法:静的メンバー変数に一度に値を割り当てるため。

静的ブロックを使用してプログラムのパフォーマンスを最適化できるのは、その特性によるものです。クラスがロードされたときに1回だけ実行されます。例を見てみましょう:

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;
    }
}

したがって、多くの場合、一度だけ実行する必要がある一部の初期化操作は、静的コードブロックに配置されます。

4)静的変数と通常のメンバー変数の違い

静的変数と通常のメンバー変数には、主に4つの違いがあります。

違い1:異なる帰属。静的変数は、オブジェクトだけでなくクラスに属します。通常のメンバー変数は、オブジェクトに属します。

違い2:ストレージ領域が異なります。静的変数はメソッド領域にあり、通常のメンバー変数はヒープ領域にあります。

違い3:ライフサイクルが異なります。静的変数のライフサイクルはクラスのライフサイクルと同じです。通常のメンバー変数とそれが属するオブジェクトのライフサイクルは同じです。

違い4:オブジェクトがシリアル化される(Serializable)場合、静的変数は除外されます(静的変数はオブジェクトではなくクラスに属するため)

5)静的と最終は一緒に何を意味しますか

静的finalは、メンバー変数とメンバーメソッドを変更するために使用されます。これは、単に「グローバル定数」として理解できます。

   对于变量,表示一旦给值就不可修改,并且通过类名可以访问。

メソッドの場合、オーバーライドできず、クラス名から直接アクセスできることを意味します。

1つの問題に特に注意してください。

staticおよびfinalによって変更されたインスタンス定数の場合、インスタンス自体は変更できませんが、一部のコンテナタイプ(ArrayList、HashMapなど)のインスタンス変数の場合、コンテナ変数自体は変更できませんが、コンテナに格納されているオブジェクトは変更できます。これはプログラミングでよく使用されます。

静的キーワードの誤解

1. staticキーワードは、クラスのメンバーのアクセス権を変更しますか?

一部の初心者の友人は、javaの静的キーワードの機能をC / C ++の静的キーワードと混同します。ここで覚えておくべきことは1つだけです。C/ C ++のstaticとは異なり、Javaのstaticキーワードは変数やメソッドのスコープに影響を与えません。Javaでは、アクセス許可に影響を与える可能性のあるキーワードは、private、public、およびprotected(パッケージのアクセス許可を含む)のみです。次の例を見て理解してください。

2.これを介して静的メンバー変数にアクセスできますか?

静的メソッドにはこれはありませんが、非静的メソッドでこれを介して静的メンバー変数にアクセスできますか?最初に次の例を見てください、このコードの出力は何ですか?

public class Main {
    
      
    static int value = 33;
 
    public static void main(String[] args) throws Exception{
    
    
        new Main().printValue();
    }
 
    private void printValue(){
    
    
        int value = 3;
        System.out.println(this.value);
    }
}

これは主に、これと静的なチームの理解を調べます。これは何の略ですか?これは現在のオブジェクトを表し、printValueがnew Main()を介して呼び出された場合、現在のオブジェクトはnew Main()を介して生成されたオブジェクトです。静的変数はオブジェクトによって利用されるため、printValueのthis.valueの値は間違いなく33です。printValueメソッド内の値はローカル変数であり、これに関連付けることはまったく不可能であるため、出力結果は33になります。ここで常に1つのことを覚えておいてください:静的メンバー変数はオブジェクトから独立していますが、オブジェクトを介してアクセスできないことを意味するわけではありません。すべての静的メソッドと静的変数は、オブジェクトを介してアクセスできます(アクセス許可が十分である限り)。

3.静的はローカル変数に作用できますか?

C / C ++では、staticはローカル変数のスコープを設定できますが、Javaでは覚えておいてください。staticはローカル変数を変更できません。理由を聞かないでください。これがJava構文のルールです。

3.一般的な書面によるインタビューの質問

以下にリストされているのは、インタビュー筆記テストで頻繁に遭遇する静的キーワードに関するいくつかの質問です。参照用として、追加するものがある場合は、以下にメッセージを残してください。

1.次のコードの出力は何ですか?

public class Test extends Base{
    
    
 
    static{
    
    
        System.out.println("test static");
    }
     
    public Test(){
    
    
        System.out.println("test constructor");
    }
     
    public static void main(String[] args) {
    
    
        new Test();
    }
}
 
class Base{
    
    
     
    static{
    
    
        System.out.println("base static");
    }
     
    public Base(){
    
    
        System.out.println("base constructor");
    }
}

出力:

base static
test static
base constructor
test constructor

これが結果である理由については、最初に説明しないでください。まず、このコードの特定の実行プロセスについて考えてみましょう。メインメソッドはプログラムのエントリポイントであるため、実行の開始時に、最初にメインメソッドを見つける必要がありますが、メインメソッドを実行する前に、 Testクラスが最初にロードされ、Testクラスがロードされると、TestクラスがBaseクラスを継承していることがわかるため、最初にBaseクラスがロードされます。Baseクラスがロードされると、静的ブロックが検出され、静的ブロックが実行されます。Baseクラスがロードされた後、引き続きTestクラスをロードし、Testクラスに静的ブロックがあることを確認して、静的ブロックを実行します。必要なクラスをロードした後、mainメソッドが実行されます。mainメソッドでnewTest()を実行すると、最初に親クラスのコンストラクターが呼び出され、次に独自のコンストラクターが呼び出されます。したがって、上記の出力結果が表示されます。

2.このコードの出力は何ですか?

public class Test {
    
    
    Person person = new Person("Test");
    static{
    
    
        System.out.println("test static");
    }
     
    public Test() {
    
    
        System.out.println("test constructor");
    }
     
    public static void main(String[] args) {
    
    
        new MyClass();
    }
}
 
class Person{
    
    
    static{
    
    
        System.out.println("person static");
    }
    public Person(String str) {
    
    
        System.out.println("person "+str);
    }
}
 
 
class MyClass extends Test {
    
    
    Person person = new Person("MyClass");
    static{
    
    
        System.out.println("myclass static");
    }
     
    public MyClass() {
    
    
        System.out.println("myclass constructor");
    }
}

出力:

test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor

同様に、このコードの特定の実行プロセスについて考えてみましょう。最初にTestクラスをロードして、Testクラスの静的ブロックが実行されるようにします。次に、新しいMyClass()を実行しますが、MyClassクラスはまだロードされていないため、MyClassクラスをロードする必要があります。MyClassクラスをロードすると、MyClassクラスがTestクラスを継承していることがわかりますが、Testクラスがロードされているため、MyClassクラスのみをロードする必要があり、MyClassクラスの静的ブロックが実行されます。ロード後、オブジェクトはコンストラクターを介して生成されます。オブジェクトが生成されるとき、親クラスのメンバー変数を初期化する必要があるため、TestのPerson person = new Person()が実行され、Personクラスはまだロードされていないため、PersonクラスがロードされてPersonクラスで実行されます。の静的ブロックは、次に親クラスのコンストラクターを実行し、親クラスの初期化を完了してから、それ自体を初期化するため、MyClassでPerson person = new Person()を実行し続け、最後にMyClassのコンストラクターを実行します。

3.このコードの出力は何ですか?

public class Test {
    
    
     
    static{
    
    
        System.out.println("test static 1");
    }
    public static void main(String[] args) {
    
    
         
    }
     
    static{
    
    
        System.out.println("test static 2");
    }
}

出力:

test static 1
test static 2

mainメソッドにはステートメントはありませんが、上記の理由により出力されます。さらに、静的ブロックはクラスのどこにでも表示でき(メソッド内にない限り、メソッドは機能しないことに注意してください)、実行は静的ブロックの順序で実行されます。

見られるように:
https //zhuanlan.zhihu.com/p/70110497
https://www.cnblogs.com/dolphin0520/p/10651845.html

おすすめ

転載: blog.csdn.net/qq_30885821/article/details/109329277