java基础代码实例_基础篇:详解JAVA对象实例化过程
生活随笔
收集整理的這篇文章主要介紹了
java基础代码实例_基础篇:详解JAVA对象实例化过程
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1 對象的實例化過程
- 對象的實例化過程是分成兩部分:類的加載初始化,對象的初始化
- 要創(chuàng)建類的對象實例需要先加載并初始化該類,main方法所在的類需要先加載和初始化
- 類初始化就是執(zhí)行方法,對象實例化是執(zhí)行方法
- 一個子類要初始化需要先初始化父類
2 類的加載過程
- 類的加載機制:如果沒有相應類的class,則加載class到方法區(qū)。對應著加載->驗證->準備->解析-->初始化階段 加載:載入class對象,不一定是從class文件獲取,可以是jar包,或者動態(tài)生成的class驗證:校驗class字節(jié)流是否符合當前jvm規(guī)范準備:為類變量分配內(nèi)存并設置變量的初始值(默認值)。如果是final修飾的對象則是賦值聲明值解析:將常量池的符號引用替換為直接引用初始化:執(zhí)行類構造器(注意不是對象構造器),為類變量賦值,執(zhí)行靜態(tài)代碼塊。jvm會保證子類的執(zhí)行之前,父類的先執(zhí)行完畢
- 其中驗證、準備、解析3個部分稱為 連接
- 方法由靜態(tài)變量賦值代碼和靜態(tài)代碼塊組成;先執(zhí)行類靜態(tài)變量顯示賦值代碼,再到靜態(tài)代碼塊代碼
3 觸發(fā)類加載的條件
- 第一次創(chuàng)建類的新對象時,會觸發(fā)類的加載初始化和對象的初始化函數(shù)執(zhí)行,這個是實例初始化,其他6個都是類初始化
- JVM啟動時會先加載初始化包含main方法的類
- 調(diào)用類的靜態(tài)方法(如執(zhí)行invokestatic指令)
- 對類或接口的靜態(tài)字段執(zhí)行讀寫操作(即執(zhí)行getstatic、putstatic指令);不過final修飾的靜態(tài)字段的除外(已經(jīng)賦值,String和基本類型,不包含包裝類型),它被初始化為一個編譯時常量表達式 注意:操作靜態(tài)字段時,只有直接定義這個字段的類才會被初始化;如通過其子類來操作父類中定義的靜態(tài)字段,只會觸發(fā)父類的初始化而不是子類的初始化
- 調(diào)用JavaAPI中的反射方法時(比調(diào)用java.lang.Class中的方法(Class.forName),或者java.lang.reflect包中其他類的方法)
- 當初始化一個類時,其父類沒有初始化,則需先觸發(fā)父類的初始化(接口例外)
4 對象的實例化過程
- 對象實例化過程 其實就是執(zhí)行類構造函數(shù) 對應在字節(jié)碼文件中的()方法(稱之為實例構造器);()方法由非靜態(tài)變量、非靜態(tài)代碼塊以及對應的構造器組成 ()方法可以重載多個,類有幾個構造器就有幾個()方法()方法中的代碼執(zhí)行順序為:父類變量初始化,父類代碼塊,父類構造器,子類變量初始化,子類代碼塊,子類構造器。
- 靜態(tài)變量,靜態(tài)代碼塊,普通變量,普通代碼塊,構造器的執(zhí)行順序
- 具有父類的子類的實例化順序如下
5 類加載器和雙親委派規(guī)則,如何打破雙親委派規(guī)則
- 類加載器 通過一個類的全限定名來獲取描述此類的二進制字節(jié)流,實現(xiàn)這個動作的代碼模塊稱為類加載器任意一個類都需要其加載器和類本身來確定類在JVM的唯一性;每個類加載器都有自己的類名稱空間,同一個類class由不同的加載器加載,則被JVM判斷為不同的類
- 雙親委派模型 啟動類加載器有C++代碼實現(xiàn),是虛擬機的一部分。負責加載lib下的類庫其他的類加載器有java語言實現(xiàn),獨立于JVM,并且繼承ClassLoaderextention ClassLoader負責加載libext目錄下的類庫application ClassLoader 負責加載用戶路徑下(ClassPath)的代碼不同的類加載器加載同一個class文件會導致出現(xiàn)兩個類。而java給出解決方法是下層的加載器加委托上級的加載器去加載類,如果父類無法加載(在自己負責的目錄找不到對應的類),而交還下層類加載器去加載。如下圖
- 打破雙親委派模型 雙親委派模型并不是一個強制的約束模型,而是java設計者推薦給開發(fā)者的類加載實現(xiàn)方式雙親委派模型很好的解決各個類加載基礎類的同一問題(越基礎的類由越上層的加載器加載),但是基礎類總是作為用戶代碼調(diào)用的API,但是如果它的具體實現(xiàn)是下層的代碼,此時基礎類需要調(diào)用下層的代碼,則需要打破雙親委派模型如JNDI服務,JNDI的代碼有啟動類去加載(rt.jar),它需要調(diào)用由獨立廠商部署在應用程序classpath下的JNDI的SPI(Service Provider Interface)代碼。為了解決SPI代碼加載問題,java引入了線程上下文類加載器去加載SPI代碼。也就是父類加載器請求子類去完成類的加載動作線程上下文類加載器,線程創(chuàng)建時會從父線程繼承,如果全局范圍沒有設置過,則默認設置為application Class Loader
作者:clswcl
鏈接:https://juejin.im/post/6861940021146943502
來源:掘金
著作權歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權,非商業(yè)轉(zhuǎn)載請注明出處。
總結
以上是生活随笔為你收集整理的java基础代码实例_基础篇:详解JAVA对象实例化过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ar路由器 pppoe下发ipv6 dn
- 下一篇: 函数返回值失效