検索

ホームページ  >  に質問  >  本文

java - Static 标识的字段或者是代码块,真的是在类加载的时候初始化的吗?

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版》中找到一些线索,如下图:

所以,照这么说,是在第一次主动访问该类的时候执行?小弟好生迷惑啊....大家快说说你们的观点

PHPzPHPz2803日前715

全員に返信(8)返信します

  • ringa_lee

    ringa_lee2017-04-18 10:54:20

    クラスの初期化とオブジェクトの初期化。

    static に含まれるコード ブロックと変数は、クラスが初期化されるときにのみ実行されます。また、初期化の 5 つの条件もわかります。

    追加説明をわかりやすくお願いします。
    まず第一に、これらを同じ .java ファイルに入れても、コンパイル後は依然として 2 つの異なるクラス ファイルであることに変わりはありません。信じられない場合は、対応するパッケージの下に生成された .class ファイルを見てください。ビン。
    2 番目に、クラスが初期化されると、クラスの静的変数が初期化され、静的コード ブロックが実行されます。そのため、仮想マシンでは new、getstatic、putstatic 命令の使用、main 関数が配置されているクラス、リフレクション、親クラスなどの 5 つの初期化条件を規定しています。ただし、これら 5 つの状況を除いて、クラスの初期化をトリガーすることはできません。コードに示されているように、Main.class には、AAA.class に関する呼び出しや親子関係やリフレクションはありません。したがって、AAA.classは当然初期化されません。

    Java クラスのロードプロセスについては別のブログを読むことができます

    わかりますか?

    返事
    0
  • 阿神

    阿神2017-04-18 10:54:20

    -XX:+TraceClassLoading
    これを追加すると、AAAがロードされていないことがわかります

    返事
    0
  • PHP中文网

    PHP中文网2017-04-18 10:54:20

    ここで議論する必要がある 2 つの概念があります:

    1. クラスロードメカニズム

    2. Java、コンパイラー、バイトコード、JVM の仕様と実装。

    クラスの読み込みはクラス ローダー (クラスローダー) を通じて完了します。具体的な読み込み戦略は、一般的に、次の 2 つのタイプに分けられます。

    1. ハングリーロード。他のクラスによって参照されている限りロードします。

    2. 遅延ロード、クラスがアクセスされたときにのみロードされます。

    Java、コンパイラー、バイトコード、JVM には独自の仕様があり、その仕様を通じて連携して動作します。

    コンパイルボタンは、Java コードを標準化されたバイトコード ファイルにコンパイルします。JVM がクラスをロードするときに、各クラス (外部クラス、内部クラス、匿名クラス) が個別のバイトコード ファイル (クラス ファイル) にコンパイルされます。クラスファイル。

    コードに戻ります:

    Java レイヤーでは、2 つのクラス AAA と Main を 1 つのファイルに配置します。コンパイル後、コンパイラーは 2 つのクラス ファイル AAA.class と Main.class を生成します。

    2 つのクラスはコード構成の点では一緒ですが、コンパイル後は独立しており、Main は AAA を参照しないため、どのクラス ロード方法が使用されても、クラス AAA のロードはトリガーされず、クラス AAA のロードもトリガーされません。 AAA で静的コード ブロックを実行します。

    返事
    0
  • ringa_lee

    ringa_lee2017-04-18 10:54:20

    上の階の熱心なネチズンの皆様、ご回答いただき誠にありがとうございました!

    確認する

    実際、AAA クラスはロードされず、Main クラスのみがロードされます (質問のスクリーンショット: 4 番目の初期化条件、メイン クラスは jvm によって自動的にロードされます)

    リーリー

    結論

    クラス内の 静的フィールド|コード ブロック は、クラスがロードされるときに実際に初期化または実行されます。

    拡張機能

    クラスがjvmによってロードされたかどうかを確認するにはどうすればよいですか?

    これは私も苦労している問題です。最初は javac 命令,类就被 jvm 加载了,其实不然,该命令只是将 .java 文件转化成 jvm 能读懂的 .class ファイルを実行するだけの問題だと思いました。

    それでは、クラスが jvm によってロードされたかどうかをどうやって知ることができるのでしょうか?
    「Java 仮想マシンの深い理解: JVM の高度な機能とベスト プラクティス 第 2 版」とネチズンからの熱心な回答によると、いつロードされるかを規定する明確なタイミングはありません。

    でも! jvm クラスが初期化されるタイミングを明確に規定しています - 質問文のスクリーンショットにある 4 種類です!クラスのロードはクラスの初期化よりも優先されるため、ここでは、これらの状況がクラスのロードをトリガーする条件であると一時的に考えることができます。

    私の兄は無知で間違ったことを要約しているので、修正してください。ありがとう

    返事
    0
  • PHPz

    PHPz2017-04-18 10:54:20

    Main.java と AAA.java を同じフォルダーに配置します。

    main関数に記述します

    リーリー

    実行

    返事
    0
  • 大家讲道理

    大家讲道理2017-04-18 10:54:20

    mainメソッドを実行するとMainクラスのみがロードされますが、MainクラスではAAAクラスは使用されず、AAAとMainの2つのクラスを同じに書いても意味がありません。ファイルはそれらを同時にロードします

    返事
    0
  • 大家讲道理

    大家讲道理2017-04-18 10:54:20

    AAA クラスは他では新しいものではなく、それに対応して静的フィールドを取得または設定したり、静的メソッドを呼び出したりすることもありません。
    そのため、自動的には初期化されません。

    返事
    0
  • 迷茫

    迷茫2017-04-18 10:54:20

    2つのクラスに配置されており、publicとして宣言されたクラスのメインのクラスは使用されず、初期化されることもありません

    返事
    0
  • キャンセル返事