CodeGym /Java Blog /ランダム /Java の static 修飾子について知っておくべき 10 のこと
John Squirrels
レベル 41
San Francisco

Java の static 修飾子について知っておくべき 10 のこと

ランダム グループに公開済み
Java では、static 修飾子は、何かがクラスに直接関連していることを意味します。フィールドが静的であれば、そのフィールドはクラスに属します。メソッドが静的である場合、そのメソッドはクラスに属します。その結果、クラス名を使用して静的メソッドを呼び出したり、静的フィールドを参照したりできます。たとえば、countフィールドがクラス内で静的である場合Counter、次の式を使用して変数を参照できることを意味しますCounter.countJava の static 修飾子について知っておくべき 10 のこと - 1もちろん、アクセス修飾子を考慮する必要があります。たとえば、privateフィールドは、それが宣言されているクラス内でのみ使用できます。また、protectedフィールドは、パッケージ内のすべてのクラスだけでなく、パッケージ外のすべてのサブクラスでも使用できます。クラスに、値をインクリメントするCounter静的メソッドがあるとします。increment()count分野。このメソッドを呼び出すには、 を使用できますCounter.increment()Counter静的フィールドまたはメソッドにアクセスするためにクラスのインスタンスを作成する必要はありません。これが、静的 (クラス) 変数およびメソッドと非静的 (インスタンス) 変数およびメソッドの基本的な違いです。重要なメモです。クラスの静的メンバーは、クラスのインスタンスではなく、クラスに直接属していることを忘れないでください。つまり、静的count変数の値はすべてのオブジェクトで同じになりますCounter。この記事では、Java で static 修飾子を使用する基本的な側面と、主要なプログラミング概念を理解するのに役立ついくつかの機能について説明します。

Java の static 修飾子についてすべてのプログラマーが知っておくべきこと。

このセクションでは、静的メソッド、フィールド、クラスの使用の主な側面を見ていきます。変数から始めましょう。
  1. 静的メソッドやブロックなど、静的コンテキスト内のクラスの非静的メンバーにはアクセスできません。以下のコードをコンパイルするとエラーが発生します。

    
    public class Counter {
    private int count;
    public static void main(String args []) {
       System.out.println(count); //  Compile time error
    }
    }
    

    これは、Java プログラマ、特に初心者が犯しやすい間違いの 1 つです。mainメソッドは静的ですが、count変数は静的ではないため、メソッドprintln内でメソッドを使用するmainと「コンパイル時エラー」が発生します。

  2. ローカル変数とは異なり、静的フィールドとメソッドはthread safeJava にはありません。実際には、これはマルチスレッド プログラミングにおけるセキュリティ問題の最も頻繁な原因の 1 つです。クラスの各インスタンスが静的変数の同じコピーを参照していることを考慮すると、そのような変数はクラスによって保護または「ロック」される必要があります。したがって、静的変数を使用する場合は、synchronizedなどの問題を避けるために、静的変数が適切であることを確認してくださいrace conditions

  3. 静的メソッドには、呼び出すたびに新しいオブジェクトを作成する必要がないという実用的な利点があります。静的メソッドは、それを宣言するクラスの名前を使用して呼び出すことができます。だからこそ、これらのメソッドはfactoryメソッドとutilityメソッドに最適です。このjava.lang.Mathクラスは素晴らしい例です。そのほとんどすべてのメソッドは静的です。Java のユーティリティ クラスもfinal同じ理由でマークされています。

  4. もう 1 つの重要な点は、静的メソッドをオーバーライド ( ) できないことです@Override。このようなメソッドを で宣言した場合subclass、つまり、同じ名前とシグネチャを持つメソッドを宣言した場合、 のメソッドをsuperclassオーバーライドするのではなく、単に「非表示」にするだけです。この現象は として知られていますmethod hiding。これは、静的メソッドが親クラスと子の両方のクラスで宣言されている場合、呼び出されるメソッドは常にコンパイル時の変数の型に基づくことを意味します。メソッドのオーバーライドとは異なり、このようなメソッドはプログラムの実行時に実行されません。例を考えてみましょう。

    
    class Vehicle {
         public static void kmToMiles(int km) {
              System.out.println("Inside the parent class / static method");
         } 
    }
    
    class Car extends Vehicle {
         public static void kmToMiles(int km) {
              System.out.println("Inside the child class / static method");
         } 
    }
    
    public class Demo {   
       public static void main(String args []) {
          Vehicle v = new Car();
           v.kmToMiles(10);
      }
    }
    

    コンソール出力:

    親クラス/静的メソッド内

    このコードは、オブジェクトが であるにもかかわらずCar、クラス内の静的メソッドがVehicle呼び出されることを明確に示しています。これは、メソッドがコンパイル時に呼び出されたためです。コンパイル エラーがないことに注意してください。

  5. さらに、トップレベルのクラス以外のクラスも静的に宣言できます。このようなクラスは として知られていますnested static classes。これらは、より良い凝集性を提供するのに役立ちます。ネストされた静的クラスの顕著な例は ですHashMap.Entry。これは の内部のデータ構造ですHashMap。内部クラスと同様に、静的にネストされたクラスは別の .class ファイルで宣言されることに注意してください。したがって、メイン クラスで 5 つのネストされたクラスを宣言すると、.class 拡張子を持つファイルが 6 つ作成されます。別の例は、クラス内の年齢コンパレーター ( )Comparatorなど、独自の の宣言です。AgeComparatorEmployee

  6. 静的修飾子は、クラスのロード時に実行される「静的初期化ブロック」としてよく知られる静的ブロックで指定することもできます。このようなブロックを宣言しない場合、Java はすべての静的フィールドを 1 つのリストに収集し、クラスのロード時にそれらを初期化します。静的ブロックはチェックされた例外をスローできませんが、チェックされていない例外はスローできます。この場合、 がExceptionInInitializerError発生します。実際には、静的フィールドの初期化中に発生する例外はすべて、Java によってこのエラーにラップされます。NoClassDefFoundErrorこれは、クラスが参照されるときにメモリ内にないため、の最も一般的な原因でもあります。

  7. 実際のオブジェクトで呼び出されたときに実行時にリンクされる仮想メソッドや非静的メソッドのリンクとは異なり、静的メソッドはコンパイル時にリンクされることを知っておくと便利です。したがって、静的メソッドは実行時にポリモーフィズムが適用されないため、Java では静的メソッドをオーバーライドできません。これは、メソッドを静的に宣言するときに考慮すべき重要な制限です。そうすることは、サブクラス内のメソッドをオーバーライドする機能がない場合、またはその必要がない場合にのみ意味があります。ファクトリ メソッドとユーティリティ メソッドは、静的修飾子の適切な使用例です。Joshua Bloch は、すべての Java プログラマーの必読書である著書『Effective Java』の中で、静的ファクトリ メソッドがコンストラクターに比べて優れているいくつかの利点を指摘しています。

  8. 初期化は静的ブロックの重要な側面です。静的フィールドまたは変数は、クラスがメモリにロードされた後に初期化されます。初期化の順序は、Java クラスのソース ファイルで宣言された順序と同じで、上から下へです。静的フィールドはスレッドセーフな方法で初期化されるため、このプロセスはSingletonパターンの実装にも使用されます。Enum何らかの理由でを として使用しない場合はSingleton、良い代替手段があります。ただし、この場合、これは「遅延」初期化ではないことを考慮する必要があります。これは、誰かが静的フィールドを「要求」する前であっても、静的フィールドが初期化されることを意味します。オブジェクトがリソースを大量に使用する場合、またはめったに使用されない場合、静的ブロックでオブジェクトを初期化することは有利には機能しません。

  9. シリアル化中、transient変数などの静的フィールドはシリアル化されません。実際、静的フィールドにデータを保存すると、逆シリアル化後の初期 (デフォルト) 値が含まれます。たとえば、静的フィールドが の場合int、その値は逆シリアル化後にゼロになります。タイプが の場合float、値は 0.0 になります。フィールドが の場合Object、値は になりますnull。正直に言うと、これは Java ポジションの面接でシリアル化に関して最もよく聞かれる質問の 1 つです。重要なオブジェクト データを静的フィールドに保存しないでください。

  10. 最後に、静的インポートについて説明します。この修飾子は標準ステートメントと多くの共通点がありますimportが、1 つまたはすべての静的クラス メンバーをインポートできる点が異なります。静的メソッドをインポートすると、同じクラスで宣言されているかのようにアクセスできます。同様に、静的フィールドをインポートすると、クラス名を指定せずに静的フィールドにアクセスできます。この機能は Java 1.5 で登場し、適切に使用するとコードの可読性が向上します。ほとんどすべてのテスト開発者がアサート メソッド (オーバーロードされたバリアントなど) に静的インポートを使用するため、この構造は JUnit テストで最も頻繁に見つかりますassertEquals()

  11. それは今のところすべてです。すべての Java プログラマーは、上記の静的修飾子のすべての側面を知っている必要があります。この記事では、静的変数、フィールド、メソッド、初期化ブロック、インポートに関する基本情報を確認しました。また、Java プログラムを作成して理解するために知っておくべきいくつかの重要なプロパティについても触れました。静的メンバーは本格的なソフトウェア開発にとって非常に重要であるため、すべての開発者が静的メンバーの上手な使い方を習得することを願っています。」

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION