最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解析java創(chuàng)建對象的全過程

 更新時間:2025年12月16日 09:01:44   作者:IT云煙.  
文章總結(jié)了Java創(chuàng)建對象的幾種方式,包括使用new關(guān)鍵字、反射、clone和反序列化,此外,還詳細(xì)描述了創(chuàng)建對象的過程,包括類加載、內(nèi)存分配和對象初始化,最后,強(qiáng)調(diào)了并發(fā)情況下的操作原子性問題

一、java創(chuàng)建對象的幾種方式

1.1、使用new關(guān)鍵字

調(diào)用類的構(gòu)造方法創(chuàng)建對象

1.2、反射創(chuàng)建對象

1.2.1、Class.newInstance創(chuàng)建對象

1.2.2、調(diào)用構(gòu)造器再去創(chuàng)建對象Constructor.newInstance

先通過反射獲取類中無參構(gòu)造器,然后通過newInstance()獲取對象

1.3、clone實現(xiàn)

通過Clone創(chuàng)建對象,首先實體類中必須先實現(xiàn)Cloneable接口并復(fù)寫Object的clone方法(因為Object的這個方法是protected的)

1.4、反序列化

序列化:指把 Java 對象轉(zhuǎn)換為字節(jié)序列的過程;

反序列化:指把字節(jié)序列恢復(fù)為 Java 對象的過程;

此方式需要類先實現(xiàn)Serializable接口

public class TestStack {
    public static void main(String[] args) throws Exception {
        File file =new File("M:/Serializable.txt");
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
        UserParam userParam =new UserParam("hello");
        outputStream.writeObject(userParam);
        FileInputStream fileInputStream  = new FileInputStream(file);
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        UserParam userParam1 = (UserParam)objectInputStream.readObject();
        userParam1.setNickName("world");
        System.out.println(userParam1);
    }
}

二、創(chuàng)建對象的過程

當(dāng)Java虛擬機(jī)遇到一條字節(jié)碼new指令時:

1、檢查類是否已經(jīng)被加載

去常量池中查找該引用所指向的類有沒有被虛擬機(jī)加載,如果沒有被加載,那么會進(jìn)行類的加載過程。類的加載過程需要經(jīng)歷:加載、鏈接、初始化三個階段。對象的大小,在類加載完成時確定。(jdk1.8中,運(yùn)行時常量池、類常量池存在于方法區(qū)中。)

2、 為對象分配內(nèi)存空間

JVM為對象分配空間,即把一塊確定大小的內(nèi)存塊從Java堆中劃分出來。

2.1、分配空間的方式

1、指針碰撞

假設(shè)Java堆中內(nèi)存是絕對規(guī)整的,所有被使用過的內(nèi)存都被放在一邊,空閑的內(nèi)存被放在另一邊,中間放著一個指針作為分界點的指示器,那所分配內(nèi)存就僅僅是把那個指針向空閑空間方向挪動一段與對象大小相等的距離。

①正常情況

②給對象分配內(nèi)存后

這種方式的優(yōu)點是工作簡單,效率高,只需要移動指針就可以分配內(nèi)存空間。

缺點也很明顯:由于用指針碰撞分配內(nèi)存空間分為兩步:

  • 1、讀取指針當(dāng)前的位置。
  • 2、根據(jù)自身大小移動指針,不是原子操作,對象創(chuàng)建在虛擬機(jī)中是非常頻繁的操作,在并發(fā)情況下,會導(dǎo)致執(zhí)行讀操作或執(zhí)行寫操作的結(jié)果與預(yù)設(shè)的結(jié)果不一致(指針劃分不一致)。

例如:線程A要給對象分配8kb,讀取到指針當(dāng)前的位置,時間片用完,切換到線程B,線程B要給它的對象分配16kb,也讀取到指針當(dāng)前的位置(和線程A讀取到的一樣),將指針向空閑內(nèi)存方向移動16kb大小,線程B時間片用完,切換到線程A繼續(xù)執(zhí)行,由于線程A使用的指針位置還是之前讀到的。(線程不安全問題)

③針對指針碰撞線程不安全,有兩種方案:

1、同步處理(加鎖)分配內(nèi)存空間行為

采用 CAS 分配重試的方式來保證更新操作的原子性

2、把內(nèi)存分配行為按照線程,劃分在不同的內(nèi)存空間進(jìn)行

  • 即每個線程在Java堆中預(yù)先分配一小塊內(nèi)存,稱為本地線程分配緩沖(Thread Local Allocation Buffer,TLAB),哪個線程要分配內(nèi)存,就在哪個線程的本地緩沖區(qū)中分配,只有本地緩沖區(qū)用完了,分配新的緩存區(qū)時才需要同步鎖定
  • 虛擬機(jī)是否使用TLAB,可以通過-XX:+/-UseTLAB參數(shù)來設(shè)定。

2、空閑列表

如果Java堆中的內(nèi)存并不是規(guī)整的,已被使用的內(nèi)存和空閑的內(nèi)存相互交錯在一起,那就沒有辦法簡單地進(jìn)行指針碰撞了,虛擬機(jī)就必須維護(hù)一個列表,記錄上哪些內(nèi)存塊是可用的,在分配的時候從列表中找到一塊足夠大的空間劃分給對象實例,并更新列表上的記錄。

3、怎么選擇分配方式

兩種方式的選擇由 Java 堆是否規(guī)整決定,Java 堆是否規(guī)整是由選擇的垃圾收集器是否具有壓縮整理能力決定的。

①將內(nèi)存空間初始化為零值

內(nèi)存分配完成之后,虛擬機(jī)必須將分配到的內(nèi)存空間(但不包括對象頭)都初始化為零值。零值初始化意思就是對對象的字段賦0值,或者null值,這也就解釋了為什么這些字段在不需要進(jìn)程初始化時候就能直接使用。

如果使用了TLAB的話,這一項工作也可以提前至TLAB分配時順便進(jìn)行。

②對對象進(jìn)行必要的設(shè)置

例如這個對象是哪個類的實例、如何才能找到類的元數(shù)據(jù)信息、對象的哈希碼、對象的GC分代年齡等信息。這些信息存放在對象的對象頭中。

從虛擬機(jī)的視角來看,一個新的對象已經(jīng)產(chǎn)生了。但是從Java程序的視角看來,對象創(chuàng)建才剛剛開始——構(gòu)造函數(shù),即Class文件中的()方法還沒有執(zhí)行,所有的字段都為默認(rèn)的零值,對象需要的其他資源和狀態(tài)信息也還沒有按照預(yù)定的意圖構(gòu)造好。

③執(zhí)行實例的初始化方法init

init方法包含成員變量、構(gòu)造代碼塊的初始化,按照聲明的順序執(zhí)行,執(zhí)行對象的構(gòu)造方法,并把堆內(nèi)對象的首地址賦值給引用變量。至此,對象創(chuàng)建成功。

三、注意事項

并發(fā)情況下,需要考慮操作的步驟是不是原子性,如果不是,就要加鎖。

原子性就是動作不能再繼續(xù)被拆分了,讀是原子性,寫也是原子性,但是讀加上寫就不是原子性。

四、總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談Maven鏡像更換為阿里云中央倉庫(精)

    淺談Maven鏡像更換為阿里云中央倉庫(精)

    本篇文章主要介紹了Maven鏡像更換為阿里云中央倉庫(精),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • 基于mybatis中test條件中單引號雙引號的問題

    基于mybatis中test條件中單引號雙引號的問題

    這篇文章主要介紹了基于mybatis中test條件中單引號雙引號的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java根據(jù)日期計算星期幾的四種方法

    Java根據(jù)日期計算星期幾的四種方法

    在我們?nèi)粘I(yè)務(wù)代碼中,經(jīng)常要用到星期幾,下面這篇文章主要給大家介紹了關(guān)于Java根據(jù)日期計算星期幾的四種方法,文中通過代碼將每種實現(xiàn)的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 詳解SpringBoot 處理異常的幾種常見姿勢

    詳解SpringBoot 處理異常的幾種常見姿勢

    這篇文章主要介紹了詳解SpringBoot 處理異常的幾種常見姿勢,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • SpringCache框架加載/攔截原理詳解

    SpringCache框架加載/攔截原理詳解

    這篇文章主要介紹了SpringCache框架加載/攔截原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Docker與Kubernetes部署Java應(yīng)用容器化實踐指南

    Docker與Kubernetes部署Java應(yīng)用容器化實踐指南

    容器化是一種將應(yīng)用程序及其依賴打包成一個可移植的單元的方法,容器能夠在任何環(huán)境中運(yùn)行,并且具有隔離性、可擴(kuò)展性和高效性,這篇文章主要介紹了Docker與Kubernetes部署Java應(yīng)用容器化實踐指南的相關(guān)資料
    2026-05-05
  • Java如何獲取Object中Value

    Java如何獲取Object中Value

    在Java中,獲取Object中的值需依賴于對象的類型和屬性,常用方法包括使用反射、getter方法、接口或抽象類、Map等數(shù)據(jù)結(jié)構(gòu),本文給大家介紹Java如何獲取Object中Value,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • springboot使用redis的詳細(xì)步驟

    springboot使用redis的詳細(xì)步驟

    SpringBoot對常用的數(shù)據(jù)庫支持外,對NoSQL?數(shù)據(jù)庫也進(jìn)行了封裝自動化,下面這篇文章主要給大家介紹了關(guān)于springboot使用redis的詳細(xì)步驟,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • jcl與jul?log4j1?log4j2?logback日志系統(tǒng)機(jī)制及集成原理

    jcl與jul?log4j1?log4j2?logback日志系統(tǒng)機(jī)制及集成原理

    這篇文章主要介紹了jcl與jul?log4j1?log4j2?logback的集成原理,Apache?Commons-logging?通用日志框架與日志系統(tǒng)的機(jī)制,有需要的朋友可以借鑒參考下
    2022-03-03
  • Spring構(gòu)造器注入及@Autowired、lombok的@RequiredArgsConstructor的異同點說明

    Spring構(gòu)造器注入及@Autowired、lombok的@RequiredArgsConstructor的異同點說明

    本文介紹了Spring框架中構(gòu)造器注入的實現(xiàn)原理,包括Spring如何找到參數(shù)、構(gòu)造器注入與Autowired的區(qū)別,以及為什么Spring官方推薦構(gòu)造器注入,文章還強(qiáng)調(diào)了構(gòu)造器注入中使用final關(guān)鍵字的好處,并提供了代碼示例,幫助讀者更好地理解和應(yīng)用Spring的最佳實踐
    2026-03-03

最新評論

巴青县| 金塔县| 贡山| 陆丰市| 即墨市| 新巴尔虎左旗| 莫力| 湘西| 缙云县| 屏东县| 绥滨县| 屯留县| 平果县| 佛教| 泰兴市| 武夷山市| 湖州市| 马尔康县| 翁源县| 江川县| 穆棱市| 寻甸| 体育| 靖安县| 鹤山市| 巴林右旗| 江源县| 腾冲县| 梨树县| 稷山县| 榆社县| 尼勒克县| 彰化县| 汶川县| 敖汉旗| 遵义市| 手游| 兰坪| 宁夏| 剑阁县| 静安区|