【版權(quán)聲明】未經(jīng)博主同意,謝絕轉(zhuǎn)載?。ㄕ堊鹬卦瓌?chuàng),博主保留追究權(quán))
https://www.cnblogs.com/cnb-yuchen/p/17969159
出自【進(jìn)步*于辰的博客】
-
1、關(guān)于賦值
- 1.1 基本數(shù)據(jù)類型賦值
- 1.2 String類型賦值
-
2、關(guān)于String賦值
- 2.1 情形一
- 2.2 情形二
- 3、關(guān)于String與char[]的比較
-
4、不同類型引用分析
- 4.1 int
- 4.2 Integer
- 4.3 int[]
- 4.4 Integer[]
- 5、最后
1、關(guān)于賦值
參考筆記一,P74.1。
一個小結(jié):
所有引用都存于棧,而對象存于堆。引用所指向的可能存于棧,也可能存于方法區(qū)常量池。
1.1 基本數(shù)據(jù)類型賦值
在final int a
中a是常量,在int a
中a是變量。
示例:int a = 10;
a是變量,10是常量(a與10都存于棧)。令a = 20
,是將a的值直接由10改為20。
1.2 String類型賦值
在String s = "abc"
中,s是引用(也是變量,存于棧),"abc"
是字符串常量,存于方法區(qū)的字符串常量池。令s = "123"
,是將s由指向"abc"
轉(zhuǎn)為指向"123"
,若"abc"
沒有其他引用指向就會被回收。
2、關(guān)于String賦值
參考筆記一,P74.2。
2.1 情形一
以下兩種形式的定義的結(jié)果都相同,而底層分析略有不同。
形式一:
示例:
String s1 = "csdn", s2 = "csdn";
s2 = "2023";
sout s1;// 打?。篶sdn
sout s2;// 打印:2023
若方法區(qū)的字符串常量池中存在字符串常量“csdn”
,則不會重新創(chuàng)建,直接將s1
和s2
指向“csdn”
。
令s2 = "2023"
,同樣先判斷是否存在"2023"
。若不存在,則創(chuàng)建,然后將s2
由指向"csdn"
轉(zhuǎn)為指向"2023"
。
因此,最終s1
指向"csdn"
,s2
指向"2023"
。
形式二:
示例:
String s1 = "csdn", s2 = s1;
s2 = "2023";
sout s1;// 打印:csdn
sout s2;// 打?。?023
若存在“csdn”
,則不會重新創(chuàng)建,直接將s1
指向“csdn”
,然后將s2
指向s1
的指向。
后續(xù)步驟同上,故結(jié)果相同。
這就是為何明明s2 = s1
,而s2 = "2023"
,結(jié)果s2
改變、s1
不變的原因。
2.2 情形二
示例:
String s1 = "csdn", s2 = s1 + "2023", s3 = "csdn2023";
s2.equals(s3);// 結(jié)果:true
令s2 = s1 + "2023"
,會先獲取s1
的指向,是"csdn"
。
然后為"csdn"
復(fù)制一個副本,再轉(zhuǎn)為 StringBuffer,后執(zhí)行append("2023")
,最后調(diào)用toString()
,返回“csdn2023”
。
此時再判斷字符串常量池中是否存在字符串常量"csdn2023"
,若不存在,則創(chuàng)建,然后將s2
指向csdn2023”
。
因此,s2
與s3
的結(jié)果相同。
3、關(guān)于String與char[]的比較
如果大家想要了解String類的底層,看這里 → String類。
參考筆記一,P74.3。
示例:
String s1 = "csdn";
char[] arr = {'c', 's', 'd', 'n'};
s1.equals(arr);// 結(jié)果:false-------A
s1.toString().equals(arr.toString());// 結(jié)果:false-------B
// 注:第一個toString()多余,第二個toString()是在底層調(diào)用
// 我這么寫是為了方便大家理解
String類重寫了equals()
,在底層會先調(diào)用toString()
,返回值后再判斷;而char[]
不是具體類型,不存在重寫。當(dāng)然,仍會調(diào)用toString()
,即示例中的A與B等效,但調(diào)用的是Object類的toString()
(返回地址),故不等。
4、不同類型引用分析
參考筆記一,P36.5;筆記二,P38.1。
4.1 int
示例:
int a = 100, b = a;
a、b、100都存于棧,令a = 20
,是直接將a的值改為20,b的值仍為100。
4.2 Integer
關(guān)于八位有符號二進(jìn)制的表示范圍,可查閱博文《關(guān)于二進(jìn)制的原碼、補(bǔ)碼和反碼,以及表示范圍、常見位運(yùn)算符和進(jìn)制轉(zhuǎn)換的理解與簡述》的第1.2項。
Integer 類的“自動裝箱”和“自動拆箱”機(jī)制是什么?
- 包裝類都具有自動裝箱和自動拆箱的功能(以代碼的角度上說,就是會在底層調(diào)用某個方法)。
- 為包裝類Integer賦值時,自動裝箱是底層調(diào)用了
valueOf()
。這里存在一個溢出問題。因為整型常量存儲于方法區(qū)的整型常量池,而整型常量池使用8位有符號二進(jìn)制表示整型。8位有符號二進(jìn)制的表示范圍是-128 ~ 127
。若整型超出此此范圍,就是“溢出”。 -
“溢出”規(guī)定:若整型在范圍內(nèi),
valueOf()
底層創(chuàng)建整型常量,存儲于整型常量池;否則創(chuàng)建 Integer 對象,存儲于堆。
示例:
關(guān)于
valueOf()
,可參考Integer類的第4.33項。
Integer i1 = 1;
Integer i2 = new Integer(1);
Integer i3 = Integer.valueOf(1);
i1 == i2;// false
i1 == i3;// true
i2 == i3;// false
Integer i4 = 128;
Integer i5 = new Integer(128);
Integer i6 = Integer.valueOf(128);
i4 == i5;// false
i4 == i6;// false
i5 == i6;// false
底層分析:
-
i1
指向整型常量1
;i2
指向new Integer(1)
;由于1
在表示范圍內(nèi),故valueOf(1)
返回整型常量1
,則i3
也指向整型常量1
。 - 由于整型常量池僅能存儲
-128 ~ 127
的整型常量,故i4
指向new Integer(128)
;i5
指向new Integer(128)
;由于128
超出表示范圍,故valueOf(128)
返回new Integer(128)
。
擴(kuò)展一點(diǎn):
i1.equals(i2);// true
i1.equals(i3);// true
i2.equals(i3);// true
i4.equals(i5);// true
i4.equals(i6);// true
i5.equals(i6);// true
為何結(jié)果都為true
?
關(guān)于
equals()
,可參考Integer類的第4.6項。
4.3 int[]
示例:
int[] arr1 = {1, 2, 3}, arr2 = arr1;
arr1
、arr2
以及數(shù)組內(nèi)所有的值都存于棧,{1, 2, 3}
存儲于堆。
令arr1[0] = 10
,是直接將1改為10,則arr1是{10, 2, 3}
;arr2與arr1指向相同,故arr2也是{10, 2, 3}
。
4.4 Integer[]
示例:
Integer[] arr1 = {1, 2, 3}, arr2 = arr1;
與int[]
不同的是,Integer[]
內(nèi)的所有元素都不是直接的值,而是引用,并且是 Integer 引用,指向整型常量池或堆。
不過,無論指向哪里,由于arr2與arr1始終指向相同,因此,令arr1[0] = 10
,則arr1是{10, 2, 3}
,arr2同樣是{10, 2, 3}
。
5、最后
本文中的例子是為了方便大家理解java基本數(shù)據(jù)類型和引用類型賦值時的底層而簡單舉例的,不一定有實用性。
PS:
大家在看完這篇文章后肯定想吐槽:“你說了這么多,示例結(jié)果還不是與我們平時使用時的結(jié)果無差別,有什么意義。”
哈哈......結(jié)果當(dāng)然相同了,因為我闡述的是底層分析。這些呢在平時工作中一般是用不到的,因此,目的是為了讓大家對java基本數(shù)據(jù)類型和引用類型賦值時的底層有進(jìn)一步的理解。文章來源:http://www.zghlxwxcb.cn/news/detail-797279.html
本文完結(jié)。文章來源地址http://www.zghlxwxcb.cn/news/detail-797279.html
到了這里,關(guān)于[Java]關(guān)于基本數(shù)據(jù)類型與引用類型賦值時的底層分析的小結(jié)(簡述)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!