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

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

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

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

系統可能在第一次使用某個類時加載該類,也可能采用預加載機制來加載某個類。本節將會詳細介紹類加載、連接和初始化過程中的每個細節。

JVM 和類

當調用 java 命令運行某個 Java 程序時,該命令將會啟動一個 Java 虛擬機進程,不管該 Java 程序有多么復雜,該程序啟動了多少個線程,它們都處于該 Java 虛擬機進程里。正如前面介紹的,同一個 JVM 的所有線程、所有變量都處于同一個進程里,它們都使用該 JVM 進程的內存區。當系統出現以下幾種情況時,JVM 進程將被終止。

程序運行到最后正常結束。 程序運行到使用 system.exit() 或 Runtime.getRuntime().exit() 代碼處結束程序。 程序執行過程中遇到未捕獲的異常或錯誤而結束。 程序所在平臺強制結束了 JVM 進程。

從上面的介紹可以看出,當 Java 程序運行結束時,JVM 進程結束,該進程在內存中的狀態將會丟失。下面以類的類變量來說明這個問題。下面程序先定義了一個包含類變量的類。

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

上面程序中的粗體字代碼定義了一個類變量a,接下來定義一個類創建A類的實例,并訪問A對象的類變量a。

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

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

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

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

注意:兩次運行 Java 程序處于兩個不同的 JVM 進程中,兩個 JVM 之間并不會共享數據。

類的加載

當程序主動使用某個類時,如果該類還未被加載到內存中,則系統會通過加載、連接、初始化三個步驟來對該類進行初始化。如果沒有意外,JVM 將會連續完成這三個步驟,所以有時也把這三個步驟統稱為類加載或類初始化。

類加載指的是將類的 class 文件讀入內存,并為之創建一個 java.lang.Class 對象,也就是說,當程序中使用任何類時,系統都會為之建立一個 java.lang.Class 對象。

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

類的加載由類加載器完成,類加載器通常由 JVM 提供,這些類加載器也是前面所有程序運行的基礎,JVM 提供的這些類加載器通常被稱為系統類加載器。除此之外,開發者可以通過繼承 ClassLoader 基類來創建自己的類加載器。

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

從本地文件系統加載 class 文件,這是前面絕大部分示例程序的類加載方式。 從 JAR 包加載 class 文件,這種方式也是很常見的,前面介紹 JDBC 編程時用到的數據庫驅動類就放在 JAR 文件中,JVM 可以從 JAR 文件中直接加載該 class 文件。 通過網絡加載 class 文件。 把一個 Java 源文件動態編譯,并執行加載。

類加載器通常無須等到“首次使用”該類時才加載該類,Java 虛擬機規范允許系統預先加載某些類。

類的連接

當類被加載之后,系統為之生成一個對應的 Class 對象,接著將會進入連接階段,連接階段負責把類的二進制數據合并到 JRE 中。類連接又可分為如下三個階段。

(1)驗證:驗證階段用于檢驗被加載的類是否有正確的內部結構,并和其他類協調一致。(2)準備:類準備階段則負責為類的類變量分配內存,并設置默認初始值。(3)解析:將類的二進制數據中的符號引用替換成直接引用。

類的初始化在類的初始化階段,虛擬機負責對類進行初始化,主要就是對類變量進行初始化。在 Java 類中對類變量指定初始值有兩種方式:

①聲明類變量時指定初始值;

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

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

對于上面代碼,程序為類變量a、b都顯式指定了初始值,所以這兩個類變量的值分別為5、6,但類變量c則沒有指定初始值,它將采用默認初始值0。

聲明變量時指定初始值,靜態初始化塊都將被當成類的初始化語句,JVM 會按這些語句在程序中的排列順序依次執行它們,例如下面的類。

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

上面代碼先在靜態初始化塊中為b變量賦值,此時類變量b的值為6;接著程序向下執行,執行到①號代碼處,這行代碼也屬于該類的初始化語句,所以程序再次為類變量b賦值。也就是說,當 Test 類初始化結束后,該類的類變量b的值為9。

JVM 初始化一個類包含如下幾個步驟。

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

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

類初始化的時機

當 Java 程序首次通過下面6種方式來使用某個類或接口時,系統就會初始化該類或接口。

創建類的實例。為某個類創建實例的方式包括:使用 new 操作符來創建實例,通過反射來創建實例,通過反序列化的方式來創建實例。 調用某個類的類方法(靜態方法)。 訪問某個類或接口的類變量,或為該類變量賦值。 使用反射方式來強制創建某個類或接口對應的 java.lang.Class 對象。例如代碼:Class.forName('Person'),如果系統還未初始化 Person 類,則這行代碼將會導致該 Person 類被初始化,并返回 Person 類對應的 java.lang.Class 對象。 初始化某個類的子類。當初始化某個類的子類時,該子類的所有父類都會被初始化。 直接使用 java.exe 命令來運行某個主類。當運行某個主類時,程序會先初始化該主類。

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

對于一個 final 型的類變量,如果該類變量的值在編譯時就可以確定下來,那么這個類變量相當于“宏變量”。Java 編譯器會在編譯時直接把這個類變量出現的地方替換成它的值,因此即使程序使用該靜態類變量,也不會導致該類的初始化。例如下面示例程序的結果。

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

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

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

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

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

因為上面定義的 compileConstant 類變量的值必須在運行時才可以確定,所以①處的粗體字代碼必須保留為對 MyTest 類的類變量的引用,這行代碼就變成了使用 MyTest 的類變量,這將導致 MyTest 類被初始化。

當使用 ClassLoader 類的 loadClass() 方法來加載某個類時,該方法只是加載該類,并不會執行該類的初始化。使用 Class 的 forName() 靜態方法才會導致強制初始化該類。例如如下代碼。

package com.jwen.chapter18_1;class Tester { static { System.out.println('Tester類的靜態初始化塊...'); }}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('系統加載Tester類'); // 下面語句才會初始化Tester類 Class.forName('com.jwen.chapter18_1.Tester'); }}

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

系統加載Tester類Tester類的靜態初始化塊...

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

以上就是詳解Java 類的加載、連接和初始化的詳細內容,更多關于Java 類的加載、連接和初始化的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
不卡一二三区| 日韩av自拍| 国产模特精品视频久久久久| 女人av一区| 日韩精品一二三区| 久久激情av| 美女在线视频一区| 久久久久99| 亚洲专区一区| 日韩中文字幕在线一区| 国产精选久久| 国产麻豆久久| 国产视频亚洲| 欧美私人啪啪vps| 精品一区二区三区中文字幕 | 日韩和欧美一区二区三区| 国产日韩一区二区三免费高清| 九九九精品视频| 国产精品www.| 亚洲午夜精品久久久久久app| 在线国产日韩| 国产精品久久久久久久免费观看| 激情婷婷欧美| 日韩高清一区在线| 91免费精品| 亚洲资源av| 国产福利一区二区精品秒拍 | 国产v日韩v欧美v| 欧美日韩国产亚洲一区| 欧美亚洲综合视频| 99久久www免费| 国产欧美啪啪| 黄色av一区| 麻豆国产精品视频| 视频在线在亚洲| 国产一区三区在线播放| 免费成人在线视频观看| 精品国产亚洲一区二区三区在线 | 亚洲第一区色| 国产日韩欧美在线播放不卡| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 日韩精品社区| 99久精品视频在线观看视频| 欧美亚洲自偷自偷| 午夜在线一区二区| 日韩精品91| 久久国产生活片100| 亚洲婷婷在线| 久久亚洲资源中文字| 一二三区精品| 激情欧美丁香| 色一区二区三区四区| 日本免费一区二区视频| 亚洲视频www| 久久久9色精品国产一区二区三区| 你懂的国产精品| 中文字幕免费精品| 欧美福利一区| 日本少妇一区| 高清一区二区三区av| 国产情侣久久| 一区二区精彩视频| 伊人久久大香伊蕉在人线观看热v| 麻豆精品在线| 日韩中文字幕在线一区| 亚洲国内欧美| 青青青免费在线视频| 国产激情精品一区二区三区| 日韩综合一区二区| 亚洲资源av| 国精品一区二区| 久久青草久久| 亚洲天堂资源| 高清一区二区三区av| 国产精品扒开腿做爽爽爽软件| 亚洲精品乱码| 狠狠色综合网| 999久久久亚洲| 国产成人精品一区二区三区在线| 国产精品一区二区99| 日本久久一区| 日韩三级久久| 青青国产91久久久久久| 免费精品国产的网站免费观看| 国产资源在线观看入口av| 精品国产a一区二区三区v免费| 国产日韩欧美| 欧美日韩夜夜| 国产精品视频一区二区三区四蜜臂 | 日韩高清成人在线| 中文字幕日本一区二区| 丝袜亚洲另类欧美| 日韩精品一二三区| 亚洲欧洲专区| 日韩有码av| 日韩不卡在线观看日韩不卡视频| 欧美在线精品一区| 欧美黄色一区| 国产一区二区三区久久久久久久久| 免费亚洲一区| 美女性感视频久久| 91青青国产在线观看精品| 91亚洲成人| 色老板在线视频一区二区| 在线成人动漫av| 视频一区在线视频| 欧美日韩99| 国产aa精品| 激情欧美一区二区三区| 免费日韩av片| 欧美日韩一区二区高清| 精品国产午夜| 欧美午夜精品一区二区三区电影| 国产韩日影视精品| 久久亚洲国产精品一区二区| 青青伊人久久| 精品日韩一区| 999视频精品| 在线观看亚洲精品福利片| 日韩激情精品| 四季av一区二区凹凸精品| 亚洲夜间福利| 日本在线视频一区二区| 97精品国产福利一区二区三区| 久久中文字幕二区| 天堂av一区| 国产精品yjizz视频网| re久久精品视频| 国产日韩一区二区三区在线| 97精品国产一区二区三区| 亚洲成人一区| 国产精品自在| 色爱综合av| 日韩 欧美一区二区三区| 麻豆高清免费国产一区| 精品欧美久久| 久久不见久久见国语| 国产调教精品| 不卡在线一区| 国产精品白浆| 好看的av在线不卡观看| 欧美中文一区| 日韩精品欧美| 青青国产91久久久久久| 成人免费电影网址| 亚洲精品在线a| 国产精品不卡| 视频一区欧美日韩| 日韩成人精品一区| 中文在线日韩| 91tv亚洲精品香蕉国产一区| 日本在线成人| 国产在线日韩| 电影91久久久| 日韩欧美激情电影| 久久久精品久久久久久96| 日韩免费精品| 久久天堂成人| 久久99久久人婷婷精品综合| 午夜国产精品视频| 久久精品资源| 免费在线观看不卡| se01亚洲视频| 国产精品chinese| 亚洲精品黄色| 女人av一区| 91亚洲成人| 国产香蕉精品| 亚洲图片久久| 黄色av一区| 群体交乱之放荡娇妻一区二区| 日本精品在线播放| 影院欧美亚洲| 亚洲不卡系列| 日韩a一区二区| 国产精品久久久久久模特 | 9999国产精品| 久久av综合| 日韩av网站在线观看| 午夜在线精品| 蜜桃tv一区二区三区| 手机在线电影一区| 麻豆久久久久久| 日韩精品福利一区二区三区| 91久久久精品国产| 精品丝袜在线| 日韩在线第七页| 国产精品麻豆久久| 国产日韩精品视频一区二区三区| 免费黄网站欧美| 亚洲一区不卡| 一区二区视频欧美| 国产中文一区| 久久精选视频| 免费看av不卡| 吉吉日韩欧美| 久久久国产亚洲精品| 日韩一区二区三区在线免费观看| 高清日韩中文字幕| 91亚洲自偷观看高清|