久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

您的位置:首頁技術文章
文章詳情頁

java - Static 標識的字段或者是代碼塊,真的是在類加載的時候初始化的嗎?

瀏覽:115日期:2024-01-13 18:47:13

問題描述

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 標識的代碼塊或者是字段,都是在類加載的時候就被執(zhí)行或者賦值了,但是這么一看....感覺自己的世界觀都要被刷新了。

所以此處是類沒有被加載嗎?還是說我們一直以來認為的,靜態(tài)代碼塊、字段都在類加載的時候被初始化的,這個觀點是錯誤的?

在《深入理解Java虛擬機:JVM高級特性與最佳實踐 第2版》中找到一些線索,如下圖:java - Static 標識的字段或者是代碼塊,真的是在類加載的時候初始化的嗎?

所以,照這么說,是在第一次主動訪問該類的時候執(zhí)行?小弟好生迷惑啊....大家快說說你們的觀點

問題解答

回答1:

類初始化和對象初始化。

static包含的代碼塊和變量只有在類初始化的時候才執(zhí)行,而初始化的五種條件你也知道啦。

補充說明清楚吧。首先,你即使放在同一個.java文件中,編譯后,這還是兩個不同的class文件,不信你看看bin對應的包下面生成的.class文件。第二,類初始化的時候,就會初始化類的靜態(tài)變量和運行靜態(tài)代碼塊。所以,虛擬機規(guī)定了五種初始化的條件,比如使用了new,getstatic,putstatic指令,main函數(shù)所在的類,反射,父類等情況。而,除開這五種情況,是不能觸發(fā)類的初始化的。正如你代碼中所示Main.class中,并沒有任何關于AAA.class的調用或者父子關系或者反射。所以,AAA.class自然不會初始化。

可以看看的另一篇博客java類的加載過程

明白了嗎?

回答2:

-XX:+TraceClassLoading加上這個會發(fā)現(xiàn)沒加載AAA

回答3:

這里有兩個概念需要擼一下:

類加載機制

Java、編譯器、字節(jié)碼、JVM的規(guī)范和實現(xiàn)。

類的加載是通過類加載器(Classloader)完成的,加載的具體策略依賴JVM的具體實現(xiàn),總的來說可以分兩種:

饑餓式加載,只要被其他類引用到了就加載。

懶惰式加載,當類被訪問的時候才加載。

Java、編譯器、字節(jié)碼、JVM有各自的規(guī)范,彼此通過規(guī)范協(xié)同工作:

編譯按把Java代碼編譯成規(guī)范的字節(jié)碼文件,每一個類(外部類、內部類、匿名類)都會被編譯成一個單獨的字節(jié)碼文件(class文件),JVM加載類的時候就是從這些class文件中一個個的加載。

現(xiàn)在回到你的代碼:

在Java層,你把AAA、Main兩個類放在一個文件中,編譯器編譯后生成兩個class文件:AAA.class、Main.class。兩個類在代碼組織形式上是一起的,但是編譯后卻是獨立的,并且Main并沒有引用AAA,所以無論是哪種類加載方式都不會觸發(fā)對類AAA的加載,也就不會執(zhí)行AAA中的靜態(tài)代碼塊。

回答4:

真心感謝樓上熱心網(wǎng)友們的解答!

驗證

AAA 類確實沒有被加載,只有 Main 類被加載(題干截圖:初始化條件第四條,主類被 jvm 自動加載)

java -XX:+TraceClassLoading Main結論

類中 靜態(tài)字段|代碼塊 真的是在類加載的時候被初始化或者是執(zhí)行的!

延伸怎么知道類有沒有被 jvm 所加載?

這也是我一直糾結的問題,一開始以為只要執(zhí)行了 javac 命令,類就被 jvm 加載了,其實不然,該命令只是將 .java 文件轉化成 jvm 能讀懂的 .class 文件而已。

那么到底怎么知道類有沒有被 jvm 所加載?據(jù) 《深入理解Java虛擬機:JVM高級特性與最佳實踐 第2版》 和廣大網(wǎng)友的熱心解答可知,并沒有明確的時機規(guī)定了啥時候會被加載!

但是!jvm 明確規(guī)定了類被初始化的時機-就是題干上截圖部分那四種!而類的加載是優(yōu)先于類初始化的,所以這里,我們暫且可以認為這幾種情況就是觸發(fā)類加載的條件。

小弟愚昧,總結不妥之處,還麻煩大家指正!感謝

回答5:

把你的Main.java和AAA.java放在同一個文件夾里,

在main函數(shù)里寫

Class.forName('AAA');

執(zhí)行

回答6:

執(zhí)行main方法時,只會加載Main類,Main類中并沒有使用到AAA類,并不會去加載AAA類,并不是說把AAA和Main兩個類寫到同一個文件就會同時加載

回答7:

AAA這個類既沒有在其他地方new,也沒有對應的去獲取或者設置靜態(tài)的字段,也沒有去invoke靜態(tài)方法。所以不會自動初始化的。

回答8:

放在兩個類里面了,聲明為public的類中的mian開始執(zhí)行,那個類沒被用到自然不會被加載更別提初始化

標簽: java
主站蜘蛛池模板: 聂荣县| 库尔勒市| 溧阳市| 兰溪市| 双柏县| 右玉县| 交口县| 井陉县| 凤山市| 萨嘎县| 雅安市| 沿河| 武汉市| 浮山县| 沐川县| 屏山县| 招远市| 灌南县| 若尔盖县| 阿尔山市| 湘潭县| 金昌市| 河津市| 永定县| 柯坪县| 长子县| 将乐县| 彭山县| 文昌市| 长宁县| 普宁市| 台山市| 仁布县| 台南市| 大埔区| 两当县| 开远市| 营山县| 苏尼特左旗| 新晃| 孝昌县|