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
キーワードを使用できません -
インスタンス、クラスメソッド、および以下の組み合わせ
変数は有効です。
-
インスタンスメソッドは、インスタンスメソッドとインスタンスメソッドの両方に直接アクセスできます.
インスタンス変数
。インスタンスメソッドは
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]を見つけることができる。