開発者ドキュメント

Javaのstaticキーワードの手引き


1前書き

この記事では、Java言語の

static

キーワードについて詳しく説明します。キーワード

static

を変数、メソッド、ブロック、入れ子になったクラスにどのように適用できるか、またその違いについて説明します。


2

static

キーワードの構造

Javaプログラミング言語では、キーワード

static

は、特定のメンバーがその型のインスタンスではなく型自体に属していることを示します。

これは、その静的メンバーのインスタンスが1つだけ作成され、それがクラスのすべてのインスタンスで共有されることを意味します。

キーワードは、変数、メソッド、ブロック、およびネストクラスに適用できます。


3静的フィールド(またはクラス変数)

Javaでは、** フィールドが

static

として宣言されている場合、そのフィールドの正確な単一コピーが作成され、そのクラスのすべてのインスタンス間で共有されます。クラスを初期化する回数は関係ありません。それに属する

static

フィールドのコピーは常に1つだけです。この

static

フィールドの値は、任意の異なるクラスの同じオブジェクトのすべてのオブジェクトにわたって共有されます。

メモリの観点から見ると、

静的変数はMetaspace

と呼ばれるJVMメモリ内の特定のプールに入ります(Java 8より前は、このプールはPermanent GenerationまたはPermGenと呼ばれ、完全に削除されMetaspaceに置き換えられました)。


3.1.



static

フィールドの例

いくつかの属性(インスタンス変数)を持つ

Car

クラスがあるとします。

.

新しいオブジェクトがこの

Car

ブループリントから初期化されるときはいつでも、それぞれの新しいオブジェクトはこれらのインスタンス変数の個別のコピーを持ちます。

しかし、初期化される

Car

オブジェクトの数のカウントを保持し、すべてのインスタンスで共有され、初期化時にそれにアクセスして増分できるように変数を探しているとします。

それが

static

変数が入ってくる場所です:

public class Car {
    private String name;
    private String engine;

    public static int numberOfCars;

    public Car(String name, String engine) {
        this.name = name;
        this.engine = engine;
        numberOfCars++;
    }

   //getters and setters
}

初期化されるこのクラスのすべてのオブジェクトに対して、

numberOfCars

変数の同じコピーが増分されます。したがって、この場合は、次のようになります。

@Test
public void whenNumberOfCarObjectsInitialized__thenStaticCounterIncreases() {
    new Car("Jaguar", "V8");
    new Car("Bugatti", "W16");

    assertEquals(2, Car.numberOfCars);
}


3.2.

静的

フィールドを使用する強力な理由

  • 変数の値がオブジェクトから独立している場合

  • 値がすべてのオブジェクトにわたって共有されると想定される


3.3. 覚えておくべきポイント


  • static

    変数はクラスに属しているので、アクセスすることができます。

クラス名を直接使用し、オブジェクト参照を必要としない
**

static

変数はクラスレベルでのみ宣言できます


  • static

    フィールドはオブジェクトの初期化なしでアクセスできます

  • オブジェクト参照を使用して

    static

    フィールドにアクセスすることはできますが、


ford.numberOfCars

)、この場合はインスタンス変数かクラス変数かを判断するのが難しくなるため、使用を控える必要があります。代わりに、クラス名を使用して常に

static

変数を参照する必要があります(たとえば、この場合は

Car.numberOfCars


4静的メソッド(またはクラスメソッド)


static

フィールドと同様に、

static

メソッドもオブジェクトではなくクラスに属しているため、それらが属するクラスのオブジェクトを作成せずに呼び出すことができます。それらはクラスのオブジェクトを作成せずに使用されることを意図しています。


4.1.

static

メソッドの例

静的メソッドは通常、インスタンスの作成に依存しない操作を実行するために使用されます。

そのクラスのすべてのインスタンスで共有されるはずのコードがある場合は、そのコードを

static

メソッドに書き込みます。

public static void setNumberOfCars(int numberOfCars) {
    Car.numberOfCars = numberOfCars;
}

静的メソッドは、ユーティリティクラスやヘルパークラスを作成するためにも広く使用されているため、これらのクラスの新しいオブジェクトを作成しなくても取得できます。


Collections

またはhttps://docs.oracle.com/javase/8/docs/をご覧ください。 api/java/lang/Math.html JDKの[Math]ユーティリティクラス、https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html[StringUtils]からApacheまたはhttps://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/util/CollectionUtils.html[CollectionUtils]からSpringフレームワークにアクセスし、すべてのメソッドが

static

であることに注意してください。


4.2. 静的メソッドを使用する強力な理由

  • 静的変数や他の静的メソッドにアクセス/操作する

物に頼らないで
**

static

メソッドはユーティリティクラスやヘルパークラスで広く使われています


4.3. 覚えておくべきポイント

Javaの** 静的メソッドはコンパイル時に解決されます。メソッド以来

オーバーライドはRuntime Polymorphismの一部なので、静的メソッドは使用できません。
上書きされた


抽象メソッドは静的にはできません


  • static

    メソッドは

    this

    または

    super

    キーワードを使用できません

  • インスタンス、クラスメソッド、および以下の組み合わせ

変数は有効です。

  1. インスタンスメソッドは、インスタンスメソッドとインスタンスメソッドの両方に直接アクセスできます.

インスタンス変数
。インスタンスメソッドは

static

変数と

static

にもアクセスできます。

直接メソッド


static

メソッドはすべての

static

変数と他の

static

変数にアクセスできます。

方法
。 **

static

メソッドはインスタンス変数とインスタンスにアクセスできません

メソッドは直接** そのためにはオブジェクト参照が必要です。


5静的ブロック


static

ブロックは、

static

変数を初期化するために使用されます。

static

変数は宣言中に直接初期化することができますが、複数行の処理が必要になる場合があります。

そのような場合、静的ブロックは便利です。

初期化中に

static

変数に追加の複数ステートメントのロジックが必要な場合は、

static

ブロックを使用できます。


5.1.

static

ブロックの例

リストオブジェクトをいくつかの定義済みの値で初期化したいとします。

これは

static

ブロックで簡単になります。

public class StaticBlockDemo {
    public static List<String> ranks = new LinkedList<>();

    static {
        ranks.add("Lieutenant");
        ranks.add("Captain");
        ranks.add("Major");
    }

    static {
        ranks.add("Colonel");
        ranks.add("General");
    }
}

この例では、宣言とともにすべての初期値で

List

オブジェクトを初期化することはできません。これが、ここで

static

ブロックを使用した理由です。


5.2. 静的ブロックを使用する強力な理由


  • static

    変数の初期化に追加のロジックが必要な場合

割り当て以外
静的変数の初期化がエラーを起こしやすく、必要

例外処理


5.3. 覚えておくべきポイント

  • クラスは複数の

    static

    ブロックを持つことができます


  • static

    フィールドと

    static

    ブロックは、システム内で解決され実行されます。

それらがクラスに存在するのと同じ順序


6. 静的クラス

Javaプログラミング言語を使用すると、クラス内にクラスを作成できます。これは、一箇所でしか使用されない要素をグループ化するための説得力のある方法を提供します。これは、コードをより整理して読みやすくするのに役立ちます。

ネストしたクラスアーキテクチャは2つに分けられます。


  • static

    と宣言されている入れ子になったクラスは**

    static

    nestedと呼ばれます。

クラス**
静的ではない入れ子クラスは、内部クラスと呼ばれます。

これら2つの主な違いは、

static

ネストしたクラスは外側のクラスの静的メンバーにしかアクセスできないのに対し、内側のクラスは包含クラスのすべてのメンバー(privateを含む)にアクセスできることです。

実際、**

static

ネストされたクラスは他のトップレベルクラスと全く同じように振る舞いますが、より良いパッケージ化の便宜を提供するためにそれにアクセスする唯一のクラスに囲まれています。


6.1.

static

クラスの例

シングルトンオブジェクトを作成するために最も広く使用されているアプローチは

static

ネストされたクラスを通してです。

public class Singleton  {
    private Singleton() {}

    private static class SingletonHolder {
        public static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}


6.2.

static

内部クラスを使用する必要がある理由

  • 1か所でしか使われないグループ化クラス

カプセル化
** コードは使用する1つだけになる場所に近づいて

それ;これにより読みやすさが向上し、コードの保守性が向上します
** ネストしたクラスがそれを含むクラスへのアクセスを必要としない場合

インスタンスメンバーの場合は、

static

として宣言したほうが良いでしょう。この方法では、外部クラスと結び付けられず、したがってヒープメモリやスタックメモリを必要としないため、より最適になるからです。


6.3. 覚えておくべきポイント

  • **

    static

    ネストクラスは、のインスタンスメンバーにアクセスできません。

外側のクラスを囲むそれはオブジェクトのオブジェクトを通してのみそれらにアクセスすることができます
参照
** 静的ネストクラスは、それを囲む静的メンバすべてにアクセスできます

プライベートクラスを含むクラス
** Javaプログラミング仕様は、私たちが宣言することを許可しません

最上位クラスは

static

です。クラス内のクラス(ネストしたクラス)のみを

static

として作成できます。


7. 結論

この記事では、

static

キーワードの動作を説明しました。また、静的フィールド、静的メソッド、静的ブロック、および静的内部クラスを使用する理由と利点についても説明します。

いつものように、我々は完全なコードhttps://github.com/eugenp/tutorials/tree/master/core-java-lang-oop[over on GitHub]を見つけることができる。

モバイルバージョンを終了