class AAA {
static {
System.out.println("class AAA static block println"); // 并没有打印此句
}
}
public class Main {
public static void main(String[] args) {
System.out.println("hello world!");
}
}
一直以来都以为 static 标识的代码块或者是字段,都是在类加载的时候就被执行或者赋值了,但是这么一看....感觉自己的世界观都要被刷新了。
所以此处是类没有被加载吗?还是说我们一直以来认为的,静态代码块、字段都在类加载的时候被初始化的,这个观点是错误的?
在《深入理解Java虚拟机:JVM高级特性与最佳实践 第2版》中找到一些线索,如下图:
所以,照这么说,是在第一次主动访问该类的时候执行?小弟好生迷惑啊....大家快说说你们的观点
クラスの初期化とオブジェクトの初期化。
static に含まれるコード ブロックと変数は、クラスが初期化されるときにのみ実行されます。また、初期化の 5 つの条件もわかります。
追加説明をわかりやすくお願いします。
まず第一に、これらを同じ .java ファイルに入れても、コンパイル後は依然として 2 つの異なるクラス ファイルであることに変わりはありません。信じられない場合は、対応するパッケージの下に生成された .class ファイルを見てください。ビン。
2 番目に、クラスが初期化されると、クラスの静的変数が初期化され、静的コード ブロックが実行されます。そのため、仮想マシンでは new、getstatic、putstatic 命令の使用、main 関数が配置されているクラス、リフレクション、親クラスなどの 5 つの初期化条件を規定しています。ただし、これら 5 つの状況を除いて、クラスの初期化をトリガーすることはできません。コードに示されているように、Main.class には、AAA.class に関する呼び出しや親子関係やリフレクションはありません。したがって、AAA.classは当然初期化されません。
Java クラスのロードプロセスについては別のブログを読むことができます
わかりますか?
-XX:+TraceClassLoading
これを追加すると、AAAがロードされていないことがわかります
ここで議論する必要がある 2 つの概念があります:
クラスロードメカニズム
Java、コンパイラー、バイトコード、JVM の仕様と実装。
クラスの読み込みはクラス ローダー (クラスローダー) を通じて完了します。具体的な読み込み戦略は、一般的に、次の 2 つのタイプに分けられます。
2 つのクラスはコード構成の点では一緒ですが、コンパイル後は独立しており、Main は AAA を参照しないため、どのクラス ロード方法が使用されても、クラス AAA のロードはトリガーされず、クラス AAA のロードもトリガーされません。 AAA で静的コード ブロックを実行します。
上の階の熱心なネチズンの皆様、ご回答いただき誠にありがとうございました!
確認する
実際、AAA クラスはロードされず、Main クラスのみがロードされます (質問のスクリーンショット: 4 番目の初期化条件、メイン クラスは jvm によって自動的にロードされます)
リーリー結論
クラス内の 静的フィールド|コード ブロック は、クラスがロードされるときに実際に初期化または実行されます。
拡張機能
クラスがjvmによってロードされたかどうかを確認するにはどうすればよいですか?
これは私も苦労している問題です。最初は
javac
命令,类就被 jvm 加载了,其实不然,该命令只是将.java
文件转化成 jvm 能读懂的.class
ファイルを実行するだけの問題だと思いました。それでは、クラスが jvm によってロードされたかどうかをどうやって知ることができるのでしょうか?
「Java 仮想マシンの深い理解: JVM の高度な機能とベスト プラクティス 第 2 版」とネチズンからの熱心な回答によると、いつロードされるかを規定する明確なタイミングはありません。
でも! jvm クラスが初期化されるタイミングを明確に規定しています - 質問文のスクリーンショットにある 4 種類です!クラスのロードはクラスの初期化よりも優先されるため、ここでは、これらの状況がクラスのロードをトリガーする条件であると一時的に考えることができます。
私の兄は無知で間違ったことを要約しているので、修正してください。ありがとう
Main.java と AAA.java を同じフォルダーに配置します。
main関数に記述します
リーリー実行
mainメソッドを実行するとMainクラスのみがロードされますが、MainクラスではAAAクラスは使用されず、AAAとMainの2つのクラスを同じに書いても意味がありません。ファイルはそれらを同時にロードします
AAA クラスは他では新しいものではなく、それに対応して静的フィールドを取得または設定したり、静的メソッドを呼び出したりすることもありません。
そのため、自動的には初期化されません。
2つのクラスに配置されており、publicとして宣言されたクラスのメインのクラスは使用されず、初期化されることもありません
。