JAVA中的引用與對(duì)象詳解
Thinking in Java 一書中提到,引用和對(duì)象就像瑤控器和電視機(jī)。用瑤控器(引用)來操作電視機(jī)(對(duì)象),想換頻道什么的直接操作瑤控器就可以了,瑤控器再來調(diào)控電視機(jī)。如果你在房間里面走動(dòng),同時(shí)還想操作電視換頻道,你只需要攜帶瑤控器就可以了。我覺得這個(gè)比較非常好,引用是用來操作對(duì)象的,對(duì)象是由你來創(chuàng)建的。通常用new關(guān)鍵字來創(chuàng)建一個(gè)對(duì)象。那么這些對(duì)象是怎樣存儲(chǔ)的,內(nèi)存又是怎樣分配的呢?
存儲(chǔ)在什么地方?
1.寄存器(register):由于寄存器是在CPU內(nèi)部的,所以它的速度最快,但是數(shù)量有限,所以由編譯器根據(jù)需求進(jìn)行分配。
2.棧(stack):位于通用RAM中,通過棧指針的移動(dòng)來分配和釋放內(nèi)存,指針向下移動(dòng)分配新的內(nèi)存;指針向上移動(dòng)則釋放內(nèi)存。速度僅次于寄存器。創(chuàng)建程序時(shí),Java編譯器必須知道存儲(chǔ)在棧內(nèi)所有數(shù)據(jù)的確切大小和生命周期,因?yàn)樗仨毶上鄳?yīng)的代碼,以便上下移動(dòng)棧指針,這就限制了程序的靈活性。所以java中的對(duì)象并不存放在棧當(dāng)中,但對(duì)象的引用存放在棧中。
3.堆(heap):也是位于RAM中的內(nèi)存池,用于存放所有的JAVA對(duì)象。編譯器不需要知道要從堆里分配多少存儲(chǔ)區(qū)域,也不需要知道存儲(chǔ)的數(shù)據(jù)在堆里面存活多長(zhǎng)時(shí)間,因此堆要比棧靈活很多。當(dāng)你new創(chuàng)建一個(gè)對(duì)象時(shí),編譯器會(huì)自動(dòng)在堆里進(jìn)行存儲(chǔ)分配。當(dāng)然,為這種靈活性必須要付出相應(yīng)的代碼。用堆進(jìn)行存儲(chǔ)分配比用棧進(jìn)行存儲(chǔ)存儲(chǔ)需要更多的時(shí)間。
4.靜態(tài)存儲(chǔ)(static storage):這里的“靜態(tài)”是指“在固定的位置”(也在RAM里)。靜態(tài)存儲(chǔ)里存放程序運(yùn)行時(shí)一直存在的數(shù)據(jù)。你可用關(guān)鍵字static來標(biāo)識(shí)一個(gè)對(duì)象的特定元素是靜態(tài)的,即存放類中的靜態(tài)成員,但JAVA對(duì)象本身從來不會(huì)存放在靜態(tài)存儲(chǔ)空間里。
5. 常量存儲(chǔ)(constant storage):存放字符串常量和基本類型常量(public static final)。常量值通常直接存放在程序代碼內(nèi)部,它們永遠(yuǎn)不會(huì)被改變。有時(shí),在嵌入式系統(tǒng)中,常量本身會(huì)和其他部分分割離開,所以在這種情況下,可以選擇將其放在ROM中。
簡(jiǎn)單描述下垃圾回收機(jī)制
垃圾回收回收的是無任何引用的對(duì)象占據(jù)的內(nèi)存空間(堆)而不是對(duì)象本身,要注意以下3點(diǎn):
1)對(duì)象可能不會(huì)被回收,即垃圾回收不一定會(huì)執(zhí)行;
2)垃圾回收并不等于析構(gòu);
3)垃圾回收只與內(nèi)存有關(guān)。
引用計(jì)數(shù)器:一種簡(jiǎn)單但是速度很慢的垃圾回收策略。即每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)器,當(dāng)有引用連接至對(duì)象時(shí)計(jì)數(shù)器加1;當(dāng)引用離開時(shí)計(jì)數(shù)器減1。垃圾回收器會(huì)在含有全部對(duì)象的列表中遍歷,發(fā)現(xiàn)某個(gè)對(duì)象的引用計(jì)數(shù)器為0時(shí),就釋放其占用的內(nèi)存。
優(yōu)點(diǎn):引用計(jì)數(shù)收集器可以很快的執(zhí)行,交織在程序運(yùn)行中。對(duì)程序不被長(zhǎng)時(shí)間打斷的實(shí)時(shí)環(huán)境比較有利。
缺點(diǎn):無法檢測(cè)出循環(huán)引用。如父對(duì)象有一個(gè)對(duì)子對(duì)象的引用,子對(duì)象反過來引用父對(duì)象。這樣,他們的引用計(jì)數(shù)永遠(yuǎn)不可能為0。
自適應(yīng)、分代的、停止——復(fù)制、標(biāo)記——清掃 垃圾回收方法:
停止——復(fù)制:先暫停程序的運(yùn)行,然后將所有活的對(duì)象從當(dāng)前堆復(fù)制到另一個(gè)堆,沒有被復(fù)制的都是垃圾。當(dāng)對(duì)象從一個(gè)堆復(fù)制到另一個(gè)堆,它們的排列是一個(gè)挨著一個(gè)的,所以新堆保持緊湊排列。
標(biāo)記——清掃:遍歷所有的引用,找出所有活的對(duì)象,然后對(duì)它們進(jìn)行標(biāo)記,這個(gè)過程不會(huì)回收任何對(duì)象,只有全部標(biāo)記工作完成時(shí)才開始清除工作。沒有被標(biāo)記的對(duì)象將會(huì)被釋放,不發(fā)生任何復(fù)制動(dòng)作,所以剩下的堆空間不是連續(xù)的。
創(chuàng)建了幾個(gè)對(duì)象?
String s="abc"; 創(chuàng)建了幾個(gè)對(duì)象?
毫無疑問,這里面只創(chuàng)建了一個(gè)對(duì)象——“abc";
String s1="abc"; String s2=s1;創(chuàng)建了幾個(gè)對(duì)象?
仍然只有一個(gè)對(duì)象——“abc";
String s1="abc"; String s2=”abc";創(chuàng)建了幾個(gè)對(duì)象?
這里仍然只有一個(gè)對(duì)象——“abc";
String s="abc"+"def";創(chuàng)建了幾個(gè)對(duì)象?
注意,這里創(chuàng)建了三個(gè)對(duì)象:“abc"、”def"、“abcdef";
String s=new String("abc");創(chuàng)建了幾個(gè)對(duì)象?
大家也都知道是兩個(gè)對(duì)象。實(shí)際上是"abc"本身就是文字池中的一個(gè)對(duì)象,在運(yùn)行new String()時(shí),把文字池即pool中的字符串"abc"復(fù)制到堆中,并把這個(gè)對(duì)象的應(yīng)用交給s,所以創(chuàng)建了兩個(gè)String對(duì)象,一個(gè)在pool中,一個(gè)在堆中。
String s1=new String("abc");String s2=new String("abc");創(chuàng)建了幾個(gè)對(duì)象?
三個(gè)對(duì)象。"abc"是文字池中的一個(gè)對(duì)象,然后又在堆中用new String()創(chuàng)建了兩個(gè)對(duì)象。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- Java返回可變引用對(duì)象問題整理
- Java對(duì)象的四種引用方式實(shí)例分析
- 面試官:詳細(xì)談?wù)凧ava對(duì)象的4種引用方式
- 詳解Java對(duì)象的強(qiáng)、軟、弱和虛引用+ReferenceQueue
- Java中的對(duì)象和引用詳解
- Java多態(tài)和實(shí)現(xiàn)接口的類的對(duì)象賦值給接口引用的方法(推薦)
- 對(duì)Java的面對(duì)對(duì)象編程中對(duì)象和引用以及內(nèi)部類的理解
- 解析Java的JNI編程中的對(duì)象引用與內(nèi)存泄漏問題
- Java中的對(duì)象和對(duì)象引用實(shí)例淺析
- Java基礎(chǔ)教程之對(duì)象引用
- 淺析Java 對(duì)象引用和對(duì)象本身
相關(guān)文章
Java設(shè)計(jì)模式之策略模式的使用(Strategy?Pattern)
策略模式是一種行為型設(shè)計(jì)模式,用于定義一系列算法并將每個(gè)算法封裝起來,使它們可以互相替換,從而實(shí)現(xiàn)代碼的可維護(hù)性和靈活性,策略模式包含策略接口、具體策略類和上下文類,并通過將算法的選擇與使用分離,使得算法可以獨(dú)立變化2025-03-03
SpringBoot中整合MyBatis-Plus-Join使用聯(lián)表查詢的實(shí)現(xiàn)
本文主要介紹了SpringBoot中整合MyBatis-Plus-Join使用聯(lián)表查詢的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
maven子模塊相互依賴打包時(shí)報(bào)錯(cuò)找不到類的解決方案
本文主要介紹了maven子模塊相互依賴打包時(shí)報(bào)錯(cuò)找不到類的解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
idea中使用SonarLint進(jìn)行代碼規(guī)范檢測(cè)及使用方法
這篇文章主要介紹了idea中使用SonarLint進(jìn)行代碼規(guī)范檢測(cè),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08
SpringBoot 集成 Kettle的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot 集成 Kettle的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01
Spring實(shí)現(xiàn)Quartz自動(dòng)配置的方法詳解
這篇文章主要介紹了Spring實(shí)現(xiàn)Quartz自動(dòng)配置的方法詳解,如果想在應(yīng)用中使用Quartz任務(wù)調(diào)度功能,可以通過Spring Boot實(shí)現(xiàn)Quartz的自動(dòng)配置,以下介紹如何開啟Quartz自動(dòng)配置,以及Quartz自動(dòng)配置的實(shí)現(xiàn)過程,需要的朋友可以參考下2023-11-11
Java編程實(shí)現(xiàn)月食簡(jiǎn)單代碼分享
這篇文章主要介紹了Java編程實(shí)現(xiàn)月食簡(jiǎn)單代碼分享,程序很簡(jiǎn)單,喜歡的朋友可以拿過去玩玩。2017-11-11
SpringBoot?AOP?Redis實(shí)現(xiàn)延時(shí)雙刪功能實(shí)戰(zhàn)
本文主要介紹了SpringBoot?AOP?Redis實(shí)現(xiàn)延時(shí)雙刪功能實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08

