[转载] Java内存管理-你真的理解Java中的数据类型吗(十)
參考鏈接: Java中的字符串類String 1
做一個積極的人?
?編碼、改bug、提升自己?
?我有一個樂園,面向編程,春暖花開!?
?
?
?推薦閱讀?
?第一季?
?0、Java的線程安全、單例模式、JVM內(nèi)存結(jié)構(gòu)等知識梳理 1、Java內(nèi)存管理-程序運行過程(一) 2、Java內(nèi)存管理-初始JVM和JVM啟動流程(二) 3、Java內(nèi)存管理-JVM內(nèi)存模型以及JDK7和JDK8內(nèi)存模型對比總結(jié)(三) 4、Java內(nèi)存管理-掌握虛擬機類加載機制(四) 5、Java內(nèi)存管理-掌握虛擬機類加載器(五) 6、Java內(nèi)存管理-類加載器的核心源碼和設(shè)計模式(六) 7、Java內(nèi)存管理-掌握自定義類加載器的實現(xiàn)(七) 第一季總結(jié):由淺入深JAVA內(nèi)存管理 Core Story?
?
?
?第二季?
?8、Java內(nèi)存管理-愚人節(jié)new一個對象送給你(八) 【福利】JVM系列學(xué)習(xí)資源無套路贈送 9、Java內(nèi)存管理-”一文掌握虛擬機創(chuàng)建對象的秘密”(九) 10、Java內(nèi)存管理-你真的理解Java中的數(shù)據(jù)類型嗎(十) 11、Java內(nèi)存管理-Stackoverflow問答-Java是傳值還是傳引用?(十一) 12、Java內(nèi)存管理-探索Java中字符串String(十二)?
?
?
?實戰(zhàn)?
?一文學(xué)會Java死鎖和CPU 100% 問題的排查技巧?
?
分享一位老師的人工智能教程。零基礎(chǔ)!通俗易懂!風(fēng)趣幽默! 大家可以看看是否對自己有幫助,點擊這里查看【人工智能教程】。接下來進(jìn)入正文。?
勿在流沙筑高臺,出來混遲早要還的。?
作為Java程序員,Java 的數(shù)據(jù)類型這個是一定要知道的! 但是不管是那種數(shù)據(jù)類型最終存儲都要到內(nèi)存中,本文由淺入深對數(shù)據(jù)類型進(jìn)行介紹和講解,相信讀完本文你一定會有收獲的,會對Java數(shù)據(jù)類型有更深的了解和認(rèn)識!?
本文地圖?
?
一、什么是位、字節(jié)、字符、字符集?
位(bit):計算機內(nèi)部存儲數(shù)據(jù)的最小單位,音譯為比特,每個二進(jìn)制數(shù)字0或者1就是1個位!?
字節(jié)(Byte):計算機**存儲容量(數(shù)據(jù)處理)**的基本單位,音譯拜特,8個位構(gòu)成一個字節(jié);即:1 byte (字節(jié))= 8 bit(位)。?
一個字節(jié)能夠存放的數(shù)字范圍用二進(jìn)制表示為00000000011111111,也就是8個bit(比特),8個比特轉(zhuǎn)換為無符號的10進(jìn)制數(shù)字范圍是0255,轉(zhuǎn)換為有符號數(shù)據(jù)一般為-128~127。?
?
字節(jié)說明:對于存儲容量,我們是比較熟悉的,計算機存儲容量大小以字節(jié)數(shù)來度量,1024進(jìn)位制:?
1024B=1K(千)B (1024個字節(jié)等于 1KB)
1024KB=1M(兆)B
1024MB=1G(吉)B
1024GB=1T(太)B
還有PB、EB、ZB、YB 、NB、DB等
?
?
字符:字符是一種符號,同以上說的存儲單位不是一回事。指計算機中使用的字母、數(shù)字、字和符號,包括:1、2、3、A、B、C、~!·#¥%……—*()——+等等。字符一般在不同的編碼(字符集)下面占用的字節(jié)數(shù)不同!也即占用存儲空間不同!?
編碼:編碼就是一個編號(數(shù)字)到字符的一種映射關(guān)系(集合),常見的有 ASCII、ISO-8859-1、GB2312、GBK、UTF-8、UTF-16 等。它們都可以被看作為字典,它們規(guī)定了轉(zhuǎn)化的規(guī)則,按照這個規(guī)則就可以讓計算機正確的表示我們的字符。?
# 簡單舉例舉例:
在 ASCII 編碼中,一個英文字母字符存儲需要1個字節(jié)。
在 GB 2312 編碼或 GBK 編碼中,一個漢字字符存儲需要2個字節(jié)。
在UTF-8編碼中,一個英文字母字符存儲需要1個字節(jié),一個漢字字符儲存需要3到4個字節(jié)。
在UTF-16編碼中,一個英文字母字符或一個漢字字符存儲都需要2個字節(jié)(Unicode擴展區(qū)的一些漢字存儲需要4個字節(jié))。
在UTF-32編碼中,世界上任何字符的存儲都需要4個字節(jié)。
?
?
tips:??
ASCII碼是最熟知字符編碼,編碼范圍為0255,屬于單字節(jié)編碼。ASCII碼編碼范圍太小了,Java為了能夠處理多字節(jié)語言編碼(比如中文、日文、韓文等)編碼范圍0x0000000x10FFFF,采用國際組織制定的Unicode編碼集。?
因為Unicode編碼并非連續(xù)的,所有將Unicode轉(zhuǎn)換為具體的數(shù)值格式是又有多種不同的轉(zhuǎn)換方式。稱為Unicode Translation Format(UTF)。?
簡單總結(jié)一下UTF-8、UTF-16、UTF-32三種轉(zhuǎn)換方式,都是采用字節(jié)作為編碼的基本單位!?
轉(zhuǎn)換方式特點優(yōu)點缺點UTF-8變長編碼,1-4字節(jié)節(jié)省空間轉(zhuǎn)換麻煩UTF-16固定編碼,2字節(jié)轉(zhuǎn)換相對簡單空間相對節(jié)省UTF-32固定編碼,4字節(jié)轉(zhuǎn)換簡單空間最浪費
目前使用UTF-8還是比較多,節(jié)省空間還是很大的優(yōu)勢! 在說明一點Java虛擬機內(nèi)部使用的UTF-16轉(zhuǎn)換方式,固定使用兩個字節(jié),所以java中字符char 占用 2個字節(jié)!??
?
編碼這一塊的內(nèi)容其實挺多,如需了解更多深入細(xì)節(jié),請自行查閱相關(guān)資料!?
二、基本數(shù)據(jù)類型和引用數(shù)據(jù)類型?
有學(xué)過C語言的伙伴知道在C語言中可以聲明指針類型的變量,但是在Java語言中是看不到使用指針的,那么Java中有沒有指針呢?準(zhǔn)確的話是有的,因為在Java底層有些類型是封裝了指針的。在Java中根據(jù)底層是否封裝了指針可以將Java的數(shù)據(jù)類型分為兩類,值類型和引用類型!?
?
2.1、值類型?
值類型: 也稱為基本數(shù)據(jù)類型和基元數(shù)據(jù)類型。它的值就是一個數(shù)字,一個字符或一個布爾值等。?
沒有封裝指針的變量,它們在Java中有8個,包括byte、char、 short、int 、float 、long 、double、boolean。?
這些基本類型首字母都是小寫,它們并不是類,也沒有屬性和方法。聲明值類型變量,只會在棧中分配一塊內(nèi)存空間。?
?
這里面還有一個知識點是: 自動類型轉(zhuǎn)換和強制類型轉(zhuǎn)換!?
自動類型轉(zhuǎn)換:?
一般情況下Java中會將占用內(nèi)存空間較低的類型轉(zhuǎn)換為較高類型,如 int型的變量和 long型的變量進(jìn)行計算的時候,會將int型轉(zhuǎn)換為long型;?
如果兩個變量占用內(nèi)存空間一樣,但是一個是整型,一個是浮點型,則會將整型轉(zhuǎn)換為浮點型。如int型變量與float型變量進(jìn)行計算,會將int型轉(zhuǎn)換為float型。?
強制類型轉(zhuǎn)換:?
第一種情況:提升變量的類型級別,以獲取精度更高的計算結(jié)果! 比如 兩個整型int變量進(jìn)行除法運算,為了精度更高,強制轉(zhuǎn)為long類型!?
第二種情況:需要用占用空間較小的變量類型接受占用空間較大的變量類型。比如 int轉(zhuǎn)為byte等,但是要注意 轉(zhuǎn)換過程中產(chǎn)生溢出截斷的情況!?
上面圖中內(nèi)容中沒有boolean類型變量進(jìn)行說明,因為boolean類型比較特殊。boolean類型變量只有兩個值,true或者false,它不參與數(shù)學(xué)運算,也不能與其他類型變量進(jìn)行轉(zhuǎn)換(不管自動轉(zhuǎn)換還是強制轉(zhuǎn)換),只是用來進(jìn)行邏輯判斷。?
boolean類型變量的內(nèi)存空間占用具有一定的不確定性,理論上一個比特就可以保存boolean類型變量的值,當(dāng)因為內(nèi)存使用的最小單位是字節(jié),那么變量不可能僅占用1/8個字節(jié)。實際中,根據(jù)編譯器的不同,**Java會使用1~4字節(jié)來保存boolean變量。**字節(jié)內(nèi)容均為0表示false。只要有字節(jié)為非0值表示true。?
面試一定要注意 :String 不是基本類型!?
2.2、引用類型?
引用類型: 就是底層封裝指針的數(shù)據(jù)類型。這部分包含的比較多,比如我們自定義或者系統(tǒng)的類、抽象類、接口,以及數(shù)組。它們在內(nèi)存中分配兩塊空間,首先要在棧上給其引用(句柄)分配一塊內(nèi)存(不存放具體數(shù)值),然后對象的具體信息都存儲在堆內(nèi)存上(如對象的屬性值等),最后由棧上面的引用指向堆中對象的地址。?
2.3、簡單示例?
示例代碼:?
public class PrettyGirl {
? ? /**
? ? ?* 姑娘姓字名誰
? ? ?*/
? ? String name;
?
? ? /**
? ? ?* 芳齡幾何
? ? ?*/
? ? int age;
?
? ? public static void main(String[] args) {
? ? ? ? //? PrettyGirl是自定義類,是引用類型,分配兩塊內(nèi)存空間
? ? ? ? PrettyGirl prettyGirl = new PrettyGirl();
?
? ? ? ? // String類是系統(tǒng)類,也是引用類型,分配兩塊內(nèi)存空間
? ? ? ? String name = new String("Java ok");
?
? ? ? ? // int,float 是值類型,只分配一塊內(nèi)存空間
? ? ? ? int num = 10;
? ? ? ? float price = 110.10f;
?
? ? ? ? // 對象名.屬性名訪問對象的屬性,訪問包括賦值和取值
? ? ? ? prettyGirl.name = "Alice";
? ? ? ? prettyGirl.age = 25;
?
? ? }
?
}
?
通過類名 對象名 = new 類名()創(chuàng)建對象, 在 PrettyGirl prettyGirl = new PrettyGirl();這行代碼在內(nèi)存中就創(chuàng)建了兩塊內(nèi)存空間,第一塊在棧中,名字叫 prettyGirl,它是一個引用地址,并不放具體的數(shù)值,第二塊堆中的內(nèi)存才存放具體的數(shù)值,如name,age等信息。?
?
其實數(shù)組內(nèi)部也是封裝引用(指針),即便是基本類型的數(shù)組,也是如此! **數(shù)組也是引用類型!**比如?
int[] nums = new int[]{1,4,7,3,9};
?
?
說明 :0x001 是我隨便寫的一個值,真實的內(nèi)存地址并不是這個,這個值只是為了我畫圖方便!?
在多強調(diào)一點,在引用類型中,對于類來說,要創(chuàng)建對象其實包括兩步,第一是聲明對象,第二是創(chuàng)建對象!?
public static void main(String[] args) {
? ? // 聲明對象,相當(dāng)分配指針類型變量,在棧中分配內(nèi)存
? ? PrettyGirl alice;
? ? // 創(chuàng)建對象,創(chuàng)建具體內(nèi)存空間,在堆中分配內(nèi)存
? ? alice = new PrettyGirl();
}
?
聲明對象:就相當(dāng)于在棧中聲明引用類型的變量,它的內(nèi)存不存放具體的數(shù)值,而只存放另一塊堆中內(nèi)存的地址!如?
PrettyGirl alice;
?
創(chuàng)建對象:一般使用new關(guān)鍵字,如下代碼?
alice = new PrettyGirl();
?
上面這一行代碼做了兩件事情,首先在堆中分配一塊存放具體數(shù)值的內(nèi)存,然后將這個內(nèi)存的首地址賦給上面聲明的引用變量!?
?
其實很多時候,對象的聲明和創(chuàng)建是放在一行的,如下:?
PrettyGirl mary = new PrettyGirl();
?
三、 八種基本類型的包裝類和常量池?
以下內(nèi)容摘自:參考資料1 中 8種基本類型的包裝類和常量池部分內(nèi)容!?
Java 基本類型的包裝類的大部分都實現(xiàn)了常量池技術(shù),即Byte,Short,Integer,Long,Character,Boolean;這5種包裝類默認(rèn)創(chuàng)建了數(shù)值[-128,127]的相應(yīng)類型的緩存數(shù)據(jù),但是超出此范圍仍然會去創(chuàng)建新的對象。?
兩種浮點數(shù)類型的包裝類 Float,Double 并沒有實現(xiàn)常量池技術(shù)。?
Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 輸出true
Integer i11 = 333;
Integer i22 = 333;
System.out.println(i11 == i22);// 輸出false
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);// 輸出false, 無緩存!
?
Integer 緩存源代碼:?
/**
*此方法將始終緩存-128到127(包括端點)范圍內(nèi)的值,并可以緩存此范圍之外的其他值。
*/
public static Integer valueOf(int i) {
? ? if (i >= IntegerCache.low && i <= IntegerCache.high)
? ? ? ? return IntegerCache.cache[i + (-IntegerCache.low)];
? ? return new Integer(i);
}
?
對于Integer類型來說,值在-128-127,用==比較是一致的,超過這個區(qū)間就不行了。?
應(yīng)用場景:?
Integer i1=40;Java 在編譯的時候會直接將代碼封裝成Integer i1=Integer.valueOf(40);,從而使用常量池中的對象。Integer i1 = new Integer(40);這種情況下會創(chuàng)建新的對象。?
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);//輸出false
?
最后在貼出阿里巴巴Java手冊中對包裝類使用的建議:?
?
四、本文總結(jié)?
本文整體內(nèi)容相對基礎(chǔ),但是在java開發(fā)中還是非常重要,注重細(xì)節(jié)和基礎(chǔ),讓寫出的每一行代碼都是最優(yōu)的!朝著這個方向努力! 下一篇整理一下值傳遞和引用傳遞! 敬請期待!?
備注: 由于本人能力有限,文中若有錯誤之處,歡迎指正。?
五、參考資料?
1、可能是把Java內(nèi)存區(qū)域講的最清楚的一篇文章?
2、Java語言中一個字符占幾個字節(jié)??
?
謝謝你的閱讀,如果您覺得這篇博文對你有幫助,請點贊或者喜歡,讓更多的人看到!祝你每天開心愉快!?
?
?
?Java編程技術(shù)樂園:一個分享編程知識的公眾號。跟著老司機一起學(xué)習(xí)干貨技術(shù)知識,每天進(jìn)步一點點,讓小的積累,帶來大的改變!
?
?
?
?掃描關(guān)注,后臺回復(fù)【資源】,獲取珍藏干貨! 99.9%的伙伴都很喜歡
?
?
?
?
???
?每天都在變得更好的阿飛云
總結(jié)
以上是生活随笔為你收集整理的[转载] Java内存管理-你真的理解Java中的数据类型吗(十)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle不要重复记录,Oracle中
- 下一篇: php ci框架 实例化类,php框架C