今日は主にJava言語のstaticキーワードを勉強します。
静的キーワードの意味と使用シナリオ
static は、Java の 50 個のキーワードの 1 つです。 static キーワードを使用すると、静的コード ブロックを表すようにコード ブロックを変更したり、グローバル静的メンバー変数を表すように変更したメンバー変数を変更したり、静的メソッドを表すように変更したメソッドを変更したりすることができます。 (注: 内部クラスを除き、通常のクラスは変更できません。これはなぜですか?)
class A { static { System.out.println("A : 静态代码块"); } static int i ; // 静态变量 static void method() { System.out.println("A: 静态方法"); } }
つまり、static キーワードによって変更された内容は静的です。
静的は動的に相対的なものです。動的とは、Java プログラムが JVM 上で実行されるときに、JVM がプログラムのニーズに応じて動的にオブジェクトを作成し、オブジェクトを格納 (メモリの割り当て) することを意味します。オブジェクトのミッション後完了すると、オブジェクトはガベージ リサイクラーによる破棄、つまり、メモリのリサイクルは JVM によって均一に管理され、新しく作成された他のオブジェクトに割り当てられます。静的とは、Java プログラムが実行される前に、JVM がロードされたクラスにスペースを割り当てることを意味します。 static キーワードによって変更されたコンテンツ (静的メンバー変数など) を保管する場合、Java クラスが JVM にロードされ、JVM はクラスとその静的メンバー変数をメソッド領域に保管します。メソッド領域は共有領域であることがわかっています。スレッドによる処理や GC はほとんど発生しないため、static キーワードによって変更されたコンテンツはグローバルに共有され、記憶域スペースは 1 回だけ割り当てられます。
したがって、クラスの一部のコンテンツがオブジェクトに属していないが、オブジェクトによって共有され、クラスに属している場合、それを変更するために static キーワードを使用するかどうかを検討できます。
静的キーワードの役割
1 コード ブロックを変更する
クラス内で static キーワードを使用して変更されたコード ブロックは、静的コードと呼ばれますおよびその逆 static キーワードで変更されていないコード ブロックは、インスタンス コード ブロックと呼ばれます。
インスタンス コード ブロックは、オブジェクトの作成時に実行されます。つまり、各オブジェクトは独自のインスタンス コード ブロックを持ちます。つまり、インスタンス コード ブロックの実行結果が現在のコンテンツの内容に影響します。オブジェクトはオブジェクトに応じて変化し、破壊されて消滅します (メモリのリサイクル)、静的コード ブロックは、Java クラスが JVM メモリにロードされるときに実行されるコード ブロックです。クラスのロードは実行中に 1 回だけ発生するため、 JVM の実行中、静的コード ブロックは 1 回だけ実行されます。
静的コード ブロックの主な機能は、複雑な初期化作業を実行することであるため、静的コード ブロックは、静的コード ブロックの実行結果を示す形式で、クラスに続くメソッド領域に格納されます。メソッド領域に格納される、つまり初期化 数量はメソッド領域に格納され、スレッドによって共有されます。
2 メンバー変数の変更
クラス内で static キーワードを使用して変更されたメンバー変数は、静的メンバー変数と呼ばれます。なぜなら、static はローカル変数を変更できないため (なぜですか?)、静的メンバー変数も変更できます。呼び出されるのは静的変数です。静的変数はコード ブロックに似ており、クラスが JVM メモリにロードされると、JVM は静的変数をメソッド領域に配置し、スレッドによって共有されるメモリを割り当てます。アクセス形式は、クラス名.静的メンバー名です。
public class StaticTest { public static void main(String[] args) { System.out.println(D.i); System.out.println(new D().i); } } class D { static { i = 2; System.out.println("D : 静态代码块1"); } static int i; }
静的変数はクラス情報に保存され、スレッド間で共有できます。もちろん、クラスのすべてのオブジェクトにも属しているため、オブジェクトを通じて静的変数にアクセスできますが、コンパイラはこれをサポートしていません. これを実行すると警告が表示されます。
注:
クラスの静的変数とクラスの静的コード ブロックの読み込み順序。クラスは最初に静的変数をロードし、次に静的コード ブロックをロードしますが、複数の静的変数と複数のコード ブロックがある場合は、書き込まれた順序でロードされます。
class D { static { i = 2; System.out.println("D : 静态代码块1"); } static { i = 6; System.out.println("D : 静态代码块2"); } static int i; }
操作の結果について考えることができます。
静的変数は明示的に初期化する必要はなく、JVM はデフォルトで対応するデフォルト値をそれらの変数に与えます。たとえば、byte の基本データ型は 0、short は 0、char は \u0000、int は 0、long は 0L、float は 0.0f、double は 0.0d、boolean は false、参照型は一律に null です。 。
静的変数は JVM メモリ内で共有され、変更できるため、それらにアクセスするとスレッド セーフティの問題が発生します (スレッド A が書き換えている間、スレッド B がその値を取得します。その場合、取得されるのは変更前の値です)。または変更された値?)、そのため、静的変数を使用する場合は、マルチスレッドを考慮する必要があります。静的変数が不変であることを確認できる場合は、final キーワードを使用してスレッド セーフティの問題を回避できます。そうでない場合は、volatile キーワードと併用するなど、同期を使用してスレッド セーフティの問題を回避する必要があります。
静的キーは、インスタンス メソッドや静的メソッドを含むローカル変数を変更できません。変更すると、静的キーワードの本来の目的である共有に違反します。
3 変更されたメソッド
static キーワードで変更されたメソッドは静的メソッドと呼ばれ、それ以外の場合はインスタンス メソッドと呼ばれます。クラス名.メソッド名を通じて呼び出されますが、静的メソッドは静的変数やクラスの他の静的メソッドを直接呼び出すことはできますが、メンバー変数やインスタンス メソッドを直接呼び出すことはできないことに注意してください (オブジェクトを通じて呼び出されない限り)。
class D { static { i = 2; System.out.println("D : 静态代码块"); } static final int i; int j; static void method() { System.out.println(i); System.out.println(new D().j); method1(); new D().method2(); } static void method1() { System.out.println(i); } void method2() { System.out.println(i); } }
注: クラスのインスタンス メソッドにはアクセスするためにオブジェクト呼び出しが必要であり、静的メソッドにはクラス名を通じて直接アクセスできるため、デプロイメント サーバーを考慮せずにクラスはどのようにして実行を開始するのでしょうか。最大の可能性は、「クラス名.静的メソッド」を通じて Java を開始することです。非常に多くの静的メソッドを定義していますが、JVM はどのようにしてメインの入り口を認識するのでしょうか?
おそらくメインの方法を思いついたのではないでしょうか。
はい、main メソッドは、Java クラスのメインの入り口として Java 仕様によって定義されています。 Java クラスの操作は main メソッドによって開始されます:
public static void main(String[] args) { for (String arg : args) { // 参数由外部定义 System.out.println(arg); }}
但注意main并不是Java关键字,它只是一个规定的程序入口的方法名字;另外main方法可以重载。
注意:static关键字虽然不能修饰普通类,但可以用static关键字修饰内部类使其变成静态内部类。static关键字本身的含义就是共享,而Java类加载到JVM内存的方法区,也是线程共享的,所以没必要用static关键字修饰普通类。
4 静态导入
在用import导入包或者类时,可以用static修饰包名或者类,表示静态导入。静态导入可以与动态导入放在一起比较来加深理解。
动态导入是当你程序运行时需要new一个不在此包中的类的对象时,才会根据全路径类名加载类;而静态导入则是随着类的加载而加载静态导入的类,所以它是提前导入的。
public class StaticTest { static void method1() { System.out.println("static method1"); } static void method2() { System.out.println("static method2"); } }
静态导入:
import static com.starry.staticImport.StaticTest.method1; public class Client { public static void main(String[] args) { method1(); // StaticTest.method2(); } }
注意method1()是静态导入,所以可以不需要通过类名访问;而method2()没有导入,则需要通过类名调用。那么什么时候需要静态导入呢?
静态导入常用于静态方法以及含有静态方法的类,枚举类等的导入,可以在编译阶段确定导入类的信息或者方法信息。
static关键字的缺点
封装是Java类的三大特性之一,也是面向对象的主要特性。因为不需要通过对象,而直接通过类就能访问类的属性和方法,这有点破坏类的封装性;所以除了Utils类,代码中应该尽量少用static关键字修饰变量和方法
以上が静的キーワードは何をするのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。