日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

詳解Java 類的加載、連接和初始化

瀏覽:33日期:2022-08-30 14:34:48

系統(tǒng)可能在第一次使用某個(gè)類時(shí)加載該類,也可能采用預(yù)加載機(jī)制來加載某個(gè)類。本節(jié)將會(huì)詳細(xì)介紹類加載、連接和初始化過程中的每個(gè)細(xì)節(jié)。

JVM 和類

當(dāng)調(diào)用 java 命令運(yùn)行某個(gè) Java 程序時(shí),該命令將會(huì)啟動(dòng)一個(gè) Java 虛擬機(jī)進(jìn)程,不管該 Java 程序有多么復(fù)雜,該程序啟動(dòng)了多少個(gè)線程,它們都處于該 Java 虛擬機(jī)進(jìn)程里。正如前面介紹的,同一個(gè) JVM 的所有線程、所有變量都處于同一個(gè)進(jìn)程里,它們都使用該 JVM 進(jìn)程的內(nèi)存區(qū)。當(dāng)系統(tǒng)出現(xiàn)以下幾種情況時(shí),JVM 進(jìn)程將被終止。

程序運(yùn)行到最后正常結(jié)束。 程序運(yùn)行到使用 system.exit() 或 Runtime.getRuntime().exit() 代碼處結(jié)束程序。 程序執(zhí)行過程中遇到未捕獲的異?;蝈e(cuò)誤而結(jié)束。 程序所在平臺(tái)強(qiáng)制結(jié)束了 JVM 進(jìn)程。

從上面的介紹可以看出,當(dāng) Java 程序運(yùn)行結(jié)束時(shí),JVM 進(jìn)程結(jié)束,該進(jìn)程在內(nèi)存中的狀態(tài)將會(huì)丟失。下面以類的類變量來說明這個(gè)問題。下面程序先定義了一個(gè)包含類變量的類。

public class A { // 定義該類的類變量 public static int a = 6;}

上面程序中的粗體字代碼定義了一個(gè)類變量a,接下來定義一個(gè)類創(chuàng)建A類的實(shí)例,并訪問A對象的類變量a。

public class ATest1 { public static void main(String[] args) { // 創(chuàng)建A類的實(shí)例 A a = new A(); // 讓a實(shí)例的類變量a的值自加 a.a++; System.out.println(a.a); }}

下面程序也創(chuàng)建A對象,并訪問其類變量a的值。

public class ATest2 { public static void main(String[] args) { // 創(chuàng)建A類的實(shí)例 A b = new A(); // 輸出b實(shí)例的類變量a的值 System.out.println(b.a); }}

在 ATest1.java 程序中創(chuàng)建了A類的實(shí)例,并讓該實(shí)例的類變量a的值自加,程序輸出該實(shí)例的類變量a的值將看到7,相信讀者對這個(gè)答案沒有疑問。關(guān)鍵是運(yùn)行第二個(gè)程序 ATest2 時(shí),程序再次創(chuàng)建了A對象,并輸出A對象類變量的a的值,此時(shí)a的值是多少呢?結(jié)果依然是6,并不是7。這是因?yàn)檫\(yùn)行 ATest1 和 ATest2 是兩次運(yùn)行 JVM 進(jìn)程,第一次運(yùn)行 JVM 結(jié)束后,它對A類所做的修改將全部丟失——第二次運(yùn)行 JVM 時(shí)將再次初始化A類。

注意:兩次運(yùn)行 Java 程序處于兩個(gè)不同的 JVM 進(jìn)程中,兩個(gè) JVM 之間并不會(huì)共享數(shù)據(jù)。

類的加載

當(dāng)程序主動(dòng)使用某個(gè)類時(shí),如果該類還未被加載到內(nèi)存中,則系統(tǒng)會(huì)通過加載、連接、初始化三個(gè)步驟來對該類進(jìn)行初始化。如果沒有意外,JVM 將會(huì)連續(xù)完成這三個(gè)步驟,所以有時(shí)也把這三個(gè)步驟統(tǒng)稱為類加載或類初始化。

類加載指的是將類的 class 文件讀入內(nèi)存,并為之創(chuàng)建一個(gè) java.lang.Class 對象,也就是說,當(dāng)程序中使用任何類時(shí),系統(tǒng)都會(huì)為之建立一個(gè) java.lang.Class 對象。

提示:前面介紹面向?qū)ο髸r(shí)提到:類是某一類對象的抽象,類是概念層次的東西.但不知道讀者有沒有想過:類也是一種對象就像平常說概念主要用于定義、描述其他事物,但概念本身也是一種事物,那么概念本身也需要被描述———這有點(diǎn)像一個(gè)哲學(xué)命題,但事實(shí)就是這樣,每個(gè)類是一批具有相同特征的對象的抽象(或者說概念),而系統(tǒng)中所有的類實(shí)際上也是實(shí)例,它們都是 java.lang.Class 的實(shí)例。

類的加載由類加載器完成,類加載器通常由 JVM 提供,這些類加載器也是前面所有程序運(yùn)行的基礎(chǔ),JVM 提供的這些類加載器通常被稱為系統(tǒng)類加載器。除此之外,開發(fā)者可以通過繼承 ClassLoader 基類來創(chuàng)建自己的類加載器。

通過使用不同的類加載器,可以從不同來源加載類的二進(jìn)制數(shù)據(jù),通常有如下幾種來源。

從本地文件系統(tǒng)加載 class 文件,這是前面絕大部分示例程序的類加載方式。 從 JAR 包加載 class 文件,這種方式也是很常見的,前面介紹 JDBC 編程時(shí)用到的數(shù)據(jù)庫驅(qū)動(dòng)類就放在 JAR 文件中,JVM 可以從 JAR 文件中直接加載該 class 文件。 通過網(wǎng)絡(luò)加載 class 文件。 把一個(gè) Java 源文件動(dòng)態(tài)編譯,并執(zhí)行加載。

類加載器通常無須等到“首次使用”該類時(shí)才加載該類,Java 虛擬機(jī)規(guī)范允許系統(tǒng)預(yù)先加載某些類。

類的連接

當(dāng)類被加載之后,系統(tǒng)為之生成一個(gè)對應(yīng)的 Class 對象,接著將會(huì)進(jìn)入連接階段,連接階段負(fù)責(zé)把類的二進(jìn)制數(shù)據(jù)合并到 JRE 中。類連接又可分為如下三個(gè)階段。

(1)驗(yàn)證:驗(yàn)證階段用于檢驗(yàn)被加載的類是否有正確的內(nèi)部結(jié)構(gòu),并和其他類協(xié)調(diào)一致。(2)準(zhǔn)備:類準(zhǔn)備階段則負(fù)責(zé)為類的類變量分配內(nèi)存,并設(shè)置默認(rèn)初始值。(3)解析:將類的二進(jìn)制數(shù)據(jù)中的符號(hào)引用替換成直接引用。

類的初始化在類的初始化階段,虛擬機(jī)負(fù)責(zé)對類進(jìn)行初始化,主要就是對類變量進(jìn)行初始化。在 Java 類中對類變量指定初始值有兩種方式:

①聲明類變量時(shí)指定初始值;

②使用靜態(tài)初始化塊為類變量指定初始值。例如下面代碼片段。

public class Test { // 聲明變量a時(shí)指定初始值 static int a = 5; static int b = 9; // ① static int c; static { // 使用靜態(tài)初始化塊為變量b指定出初始值 b = 6; System.out.println('----------'); } public static void main(String[] args) { System.out.println(Test.b); }}

對于上面代碼,程序?yàn)轭愖兞縜、b都顯式指定了初始值,所以這兩個(gè)類變量的值分別為5、6,但類變量c則沒有指定初始值,它將采用默認(rèn)初始值0。

聲明變量時(shí)指定初始值,靜態(tài)初始化塊都將被當(dāng)成類的初始化語句,JVM 會(huì)按這些語句在程序中的排列順序依次執(zhí)行它們,例如下面的類。

public class Test { static { // 使用靜態(tài)初始化塊為變量b指定出初始值 b = 6; System.out.println('----------'); } // 聲明變量a時(shí)指定初始值 static int a = 5; static int b = 9; // ① static int c; public static void main(String[] args) { System.out.println(Test.b); }}

上面代碼先在靜態(tài)初始化塊中為b變量賦值,此時(shí)類變量b的值為6;接著程序向下執(zhí)行,執(zhí)行到①號(hào)代碼處,這行代碼也屬于該類的初始化語句,所以程序再次為類變量b賦值。也就是說,當(dāng) Test 類初始化結(jié)束后,該類的類變量b的值為9。

JVM 初始化一個(gè)類包含如下幾個(gè)步驟。

①假如這個(gè)類還沒有被加載和連接,則程序先加載并連接該類。②假如該類的直接父類還沒有被初始化,則先初始化其直接父類。③假如類中有初始化語句,則系統(tǒng)依次執(zhí)行這些初始化語句。

當(dāng)執(zhí)行第2個(gè)步驟時(shí),系統(tǒng)對直接父類的初始化步驟也遵循此步驟1、3;如果該直接父類又有直接父類,則系統(tǒng)再次重復(fù)這三個(gè)步驟來先初始化這個(gè)父類......依此類推,所以 JVM 最先初始化的總是 java.lang.Object 類。當(dāng)程序主動(dòng)使用任何一個(gè)類時(shí),系統(tǒng)會(huì)保證該類以及所有父類(包括直接父類和間接父類〕都會(huì)被初始化。

類初始化的時(shí)機(jī)

當(dāng) Java 程序首次通過下面6種方式來使用某個(gè)類或接口時(shí),系統(tǒng)就會(huì)初始化該類或接口。

創(chuàng)建類的實(shí)例。為某個(gè)類創(chuàng)建實(shí)例的方式包括:使用 new 操作符來創(chuàng)建實(shí)例,通過反射來創(chuàng)建實(shí)例,通過反序列化的方式來創(chuàng)建實(shí)例。 調(diào)用某個(gè)類的類方法(靜態(tài)方法)。 訪問某個(gè)類或接口的類變量,或?yàn)樵擃愖兞抠x值。 使用反射方式來強(qiáng)制創(chuàng)建某個(gè)類或接口對應(yīng)的 java.lang.Class 對象。例如代碼:Class.forName('Person'),如果系統(tǒng)還未初始化 Person 類,則這行代碼將會(huì)導(dǎo)致該 Person 類被初始化,并返回 Person 類對應(yīng)的 java.lang.Class 對象。 初始化某個(gè)類的子類。當(dāng)初始化某個(gè)類的子類時(shí),該子類的所有父類都會(huì)被初始化。 直接使用 java.exe 命令來運(yùn)行某個(gè)主類。當(dāng)運(yùn)行某個(gè)主類時(shí),程序會(huì)先初始化該主類。

除此之外,下面的幾種情形需要特別指出。

對于一個(gè) final 型的類變量,如果該類變量的值在編譯時(shí)就可以確定下來,那么這個(gè)類變量相當(dāng)于“宏變量”。Java 編譯器會(huì)在編譯時(shí)直接把這個(gè)類變量出現(xiàn)的地方替換成它的值,因此即使程序使用該靜態(tài)類變量,也不會(huì)導(dǎo)致該類的初始化。例如下面示例程序的結(jié)果。

class MyTest { static { System.out.println('靜態(tài)初始化塊...'); } // 使用一個(gè)字符串直接量為static final的類變量賦值 static final String compileConstant = '瘋狂Java講義';}public class CompileConstantTest { public static void main(String[] args) { // 訪問、輸出MyTest中的compileConstant類變量 System.out.println(MyTest.compileConstant); // ① }}

上面程序的 MyTest 類中有一個(gè) compileConstant 的類變量,該類變量使用了 final 修飾,而且它的值可以在編譯時(shí)確定下來,因此 compileConstant 會(huì)被當(dāng)成“宏變量”處理。程序中所有使用 compileConstant 的地方都會(huì)在編譯時(shí)被直接替換成它的值——也就是說,上面程序中①處的粗體字代碼在編譯時(shí)就會(huì)被替換成“瘋狂Java講義”,所以①行代碼不會(huì)導(dǎo)致初始化 MyTest 類。

提示:當(dāng)某個(gè)類變量(也叫靜態(tài)變量)使用了 final 修飾,而且它的值可以在編譯時(shí)就確定下來,那么程序其他地方使用該類變量時(shí),實(shí)際上并沒有使用該類變量,而是相當(dāng)于使用常量。

反之,如果 final 修飾的類變量的值不能在編譯時(shí)確定下來.則必須等到運(yùn)行時(shí)才可以確定該類變量的值,如果通過該類來訪問它的類變量,則會(huì)導(dǎo)致該類被初始化。例如將上面程序中定義compileConstant 的代碼改為如下:

//采用系統(tǒng)當(dāng)前時(shí)間為 static final 類變量賦值static final String compileConstant = System.currentTimeMiIlis() + '';

因?yàn)樯厦娑x的 compileConstant 類變量的值必須在運(yùn)行時(shí)才可以確定,所以①處的粗體字代碼必須保留為對 MyTest 類的類變量的引用,這行代碼就變成了使用 MyTest 的類變量,這將導(dǎo)致 MyTest 類被初始化。

當(dāng)使用 ClassLoader 類的 loadClass() 方法來加載某個(gè)類時(shí),該方法只是加載該類,并不會(huì)執(zhí)行該類的初始化。使用 Class 的 forName() 靜態(tài)方法才會(huì)導(dǎo)致強(qiáng)制初始化該類。例如如下代碼。

package com.jwen.chapter18_1;class Tester { static { System.out.println('Tester類的靜態(tài)初始化塊...'); }}public class ClassLoaderTest { public static void main(String[] args) throws ClassNotFoundException { ClassLoader cl = ClassLoader.getSystemClassLoader(); // 下面語句僅僅是加載Tester類 cl.loadClass('com.jwen.chapter18_1.Tester'); System.out.println('系統(tǒng)加載Tester類'); // 下面語句才會(huì)初始化Tester類 Class.forName('com.jwen.chapter18_1.Tester'); }}

上面程序中的兩行粗體字代碼都用到了 Tester 類,但第一行粗體字代碼只是加載 Tester 類,并不會(huì)初始化 Tester 類。運(yùn)行上面程序,會(huì)看到如下運(yùn)行結(jié)果:

系統(tǒng)加載Tester類Tester類的靜態(tài)初始化塊...

從上面運(yùn)行結(jié)果可以看出,必須等到執(zhí)行 Class.forName('Tester') 時(shí)才完成對 Tester 類的初始化。

以上就是詳解Java 類的加載、連接和初始化的詳細(xì)內(nèi)容,更多關(guān)于Java 類的加載、連接和初始化的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
狠狠久久伊人| av中文资源在线资源免费观看| 欧美亚洲精品在线| 激情亚洲影院在线观看| 国产传媒在线观看| 88xx成人免费观看视频库| 亚洲成人av观看| 亚洲欧洲一区二区天堂久久| 亚洲一区二区成人| 视频一区国产视频| 中文字幕一区二区三区在线视频| 综合干狼人综合首页| 日韩二区三区四区| 亚洲人成在线影院| 日韩视频1区| 欧美日韩伊人| 国内精品美女在线观看| 精品捆绑调教一区二区三区| 欧洲激情综合| 中文字幕av亚洲精品一部二部| 国产日产一区| 四虎成人av| 欧美日韩国产免费观看视频| 少妇精品在线| 精品三级久久久| 欧美午夜精彩| 综合五月婷婷| 国产在线一区不卡| 99精品视频在线观看免费播放| 亚洲一区日本| 国产欧美另类| 亚洲天堂久久| 日本91福利区| 国产一区二区久久久久| 91精品二区| 日本午夜精品久久久| 动漫av一区| 国产色综合网| 精品无人区麻豆乱码久久久| 欧美日韩国产一区二区三区不卡| 香蕉久久一区| 日韩精品永久网址| 色婷婷成人网| 精品视频99| 亚洲在线成人| 精品资源在线| 丝袜亚洲另类欧美| 精品国产美女a久久9999| 红桃视频国产精品| 国产精品巨作av| 激情视频一区二区三区| 欧美亚洲一级| 五月婷婷亚洲| 国产精品www.| 红桃视频国产精品| 久久久久97| 久久亚洲不卡| 成人美女视频| 亚洲一区二区av| 国产v日韩v欧美v| 日韩成人一级| 91精品观看| 麻豆一区二区三区| 麻豆亚洲精品| 日韩不卡免费高清视频| 国产午夜一区| 日韩午夜在线| 伊人久久av| 国产精品久久久免费| av不卡在线看| 色婷婷亚洲mv天堂mv在影片| 亚洲精品美女| 午夜欧美在线| 成人国产精品| 日韩精品久久久久久久软件91| 青青久久av| 美女在线视频一区| 婷婷五月色综合香五月| 蜜桃tv一区二区三区| 精品中文字幕一区二区三区四区| 最新国产精品| 在线午夜精品| 欧美中文字幕一区二区| 不卡专区在线| 国产乱码精品一区二区三区亚洲人 | 免费在线观看视频一区| 国产一区2区在线观看| 日本综合视频| 国产亚洲精品v| 久久一区二区三区电影| 精品亚洲二区| 国产精品嫩模av在线| 亚洲日本欧美| 蜜臀av在线播放一区二区三区| 99久久精品费精品国产| 国产成人精品亚洲线观看| 久久精品97| 亚洲精品高潮| 首页国产欧美日韩丝袜| 五月婷婷六月综合| 久久国产毛片| 成人在线视频区| 国产精品sm| 国产无遮挡裸体免费久久| 亚洲精品高潮| 一区二区91| 免费毛片在线不卡| 天堂网av成人| 日本久久成人网| 久久国产主播| 久久狠狠婷婷| 亚洲调教视频在线观看| 亚洲午夜久久久久久尤物| 久久精品影视| 欧美一区二区性| 亚洲精品一二三区区别| 日韩欧美另类一区二区| 日韩欧美不卡| 99精品综合| 在线国产一区二区| 中文精品在线| 亚洲三级网址| 欧美中文一区| 国产精品欧美三级在线观看 | 美女精品在线观看| 香蕉久久夜色精品国产| 精品一区在线| 一区在线免费| 鲁大师成人一区二区三区| 伊人国产精品| 日本成人一区二区| 国产毛片精品| 荡女精品导航| 亚洲v在线看| 国产手机视频一区二区| 蜜桃av一区二区三区电影| 中文字幕成人| 欧美日韩一区二区三区在线电影| 日本精品在线播放| 欧美成人aaa| 日韩中文首页| 久久五月天小说| 蜜臀91精品一区二区三区| 日本不卡不码高清免费观看| 国产亚洲字幕| 97精品国产福利一区二区三区| 91精品xxx在线观看| 精品一区在线| 亚洲区欧美区| 欧美国产日韩电影| 性欧美videohd高精| 国产精品毛片| 日本久久一区| 成人三级高清视频在线看| 免费黄色成人| 日韩黄色av| 黄色欧美在线| 在线亚洲一区| 国产欧美视频在线| 97精品视频在线看| 亚洲一区二区三区四区五区午夜| 日韩国产91| 成人自拍av| 亚洲一二三区视频| 国产一区三区在线播放| 亚洲成人一区| 欧美在线黄色| 亚洲不卡系列| 日本伊人久久| 亚洲精品88| 日韩一二三区在线观看| 国产精品网址| 亚洲经典在线| 欧美国产视频| 伊人精品在线| 精品亚洲成人| 蜜桃久久久久久久| 岛国av免费在线观看| 亚洲精品系列| 日韩成人高清| 欧美日韩视频免费看| 日本精品不卡| 国产亚洲精品美女久久| 精品一区毛片| 久久精品二区亚洲w码| 老鸭窝亚洲一区二区三区| 国产精品色婷婷在线观看| 国产综合精品一区| 国产精品超碰| 亚洲精品a级片| 美女高潮久久久| 国产视频亚洲| 在线天堂资源www在线污| 亚洲制服欧美另类| 午夜精品成人av| 911精品国产| 午夜电影亚洲| 国产999精品在线观看| 亚洲三级观看| 欧美99久久|