Java數(shù)組與堆棧相關(guān)知識總結(jié)
一、數(shù)組創(chuàng)建
1.1 聲明并賦值
int[] a = {1,2,3};
1.2 聲明數(shù)組名開辟空間并且賦值
int[] a; a = new int[]{1,2,3};
1.3 聲明數(shù)組時指定元素個數(shù)然后賦值
int[] a= new int[3];
這里Java會默認數(shù)組元素值為0
1.4 在以上的基礎(chǔ)上創(chuàng)建多維數(shù)組
int[][] a = {{1,2,3},{4,5,6},{7,8,9}}; //每個子數(shù)組元素個數(shù)不要求均相同 int[][] a = new int[m][n]; //其中n可以省略,在創(chuàng)建的時候可以指定 int[][][] a = new int[m][n][q]; //同樣其中n、q可以省略
同樣的,在new一個數(shù)組時,如不初始化,Java會默認數(shù)組元素值為0。
二、數(shù)據(jù)類型
Java中的數(shù)據(jù)類型有兩種:
2.1 八種基本數(shù)據(jù)類型
- int
- short
- long
- byte
- float
- double
- boolean
- char
這種類型的定義是通過諸如int a = 3; long b = 255L;的形式來定義的,稱為自動變量。
自動變量存的是字面值,這些字面值固定定義在某個程序塊里面,程序塊退出后,字段值就消失了,出于追求速度的原因,就存在于棧中。
2.2 包裝類數(shù)據(jù)
包裝類的數(shù)據(jù)是如 Integer, String, Double等將相應(yīng)的基本數(shù)據(jù)類型包裝起來的類。這些類數(shù)據(jù)全部存在于堆中,Java用new()語句來顯式地告訴編譯器,在運行時才根據(jù)需要動態(tài)創(chuàng)建,因此比較靈活,但缺點是要占用更多的時間。
String是一個特殊的包裝類數(shù)據(jù)。即可以用String str = "abc";
的形式來創(chuàng)建,也可以用String str = new String("abc");
的形式來創(chuàng)建。String str = "abc";
中,并沒有通過new()來創(chuàng)建實例,因為String str = "abc";
是存儲在字符串常量池中。 字符串常量池則存在于方法區(qū)。
JVM為了提高性能和減少內(nèi)存開銷,在實例化字符串常量的時候進行了一些優(yōu)化。
1.為字符串開辟一個字符串常量池,類似于緩存區(qū)。
2.創(chuàng)建字符串常量時,首先堅持字符串常量池是否存在該字符串。存在該字符串,
3.返回引用實例,不存在,實例化該字符串并放入池中。
String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2); //true
可以看到結(jié)果是true,結(jié)果說明,JVM創(chuàng)建了兩個引用str1和str2,但只創(chuàng)建了一個對象,而且兩個引用都指向了這個對象。
String str1 = "abc"; String str2 = "abc"; str1 = "bcd"; System.out.println(str1 + "," + str2); //bcd, abc System.out.println(str1==str2); //false
參考上面的代碼可以知道,賦值的變化導致了類對象引用的變化,str1指向了另外一個新對象!而str2仍舊指向原來的對象。上例中,當我們將str1的值改為"bcd"時,JVM發(fā)現(xiàn)在棧中沒有存放該值的地址,便開辟了這個地址,并創(chuàng)建了一個新的對象,其字符串的值指向這個地址。
事實上,String類被設(shè)計成為不可改變(immutable)的類。如果你要改變其值,可以,但JVM在運行時根據(jù)新值悄悄創(chuàng)建了一個新對象,然后將這個對象的地址返回給原來類的引用。這個創(chuàng)建過程雖說是完全自動進行的,但它畢竟占用了更多的時間。在對時間要求比較敏感的環(huán)境中,會帶有一定的不良影響。
因此,并沒有與String是不可變的相矛盾。
繼續(xù)修改代碼:
String str1 = "abc"; String str2 = "abc"; str1 = "bcd"; String str3 = str1; System.out.println(str3); //bcd String str4 = "bcd"; System.out.println(str1 == str4); //true
可以看出,str3 這個對象的引用直接指向str1所指向的對象(注意,str3并沒有創(chuàng)建新對象)。當str1改完其值后,再創(chuàng)建一個String的引用str4,并指向因str1修改值而創(chuàng)建的新的對象??梢园l(fā)現(xiàn),這回str4也沒有創(chuàng)建新的對象,從而再次實現(xiàn)棧中數(shù)據(jù)的共享。
繼續(xù)修改代碼:
String str1 = new String("abc"); String str2 = "abc"; System.out.println(str1==str2); //false
可以發(fā)現(xiàn)此時返回false,這是因為通過new出來的放在了堆中,而第二個存于棧中,所以不相等。
另外:數(shù)據(jù)類型包裝類的值不可修改。不僅僅是String類的值不可修改,所有的數(shù)據(jù)類型包裝類都不能更改其內(nèi)部的值。
三、棧、棧、方法區(qū)
棧是一種連續(xù)儲存的數(shù)據(jù)結(jié)構(gòu),具有先進后出的性質(zhì)。
堆是一種非連續(xù)的樹形儲存數(shù)據(jù)結(jié)構(gòu),每個節(jié)點有一個值,整棵樹是經(jīng)過排序的。特點是根結(jié)點的值最?。ɑ蜃畲螅腋Y(jié)點的兩個子樹也是一個堆。常用來實現(xiàn)優(yōu)先隊列,存取隨意。
棧(stack)與堆(heap)都是Java用來在Ram中存放數(shù)據(jù)的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設(shè)置?;蚨选?/p>
3.1 棧
1.每個線程包含一個棧區(qū),棧中只保存基礎(chǔ)數(shù)據(jù)類型的對象和自定義對象的引用(不是對象)。
2.每個棧中的數(shù)據(jù)(原始類型和對象引用)都是私有的。
3.棧分為3個部分:基本類型變量區(qū)、執(zhí)行環(huán)境上下文、操作指令區(qū)(存放操作指令)
4.數(shù)據(jù)大小和生命周期是可以確定的,當沒有引用指向數(shù)據(jù)時,這個數(shù)據(jù)就會自動消失。
通常的操作有入棧(壓棧),出棧和棧頂元素。想要讀取棧中的某個元素,就是將其之間的所有元素出棧才能完成。
棧的優(yōu)勢是,存取速度比堆要快,僅次于直接位于CPU中的寄存器。但缺點是,存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。
另外,棧數(shù)據(jù)可以共享
類似于int a = 3;
等都是存放于棧中,當新創(chuàng)建值時Java會判斷棧中是否已存在,若存在則引用該地址,不存在則創(chuàng)建。例如:
int a = 3; int b = 3;
編譯器先處理int a = 3;首先它會在棧中創(chuàng)建一個變量為a的引用,然后查找有沒有字面值為3的地址,沒找到,就開辟一個存放3這個字面值的地址,然后將a指向3的地址。接著處理int b = 3;在創(chuàng)建完b的引用變量后,由于在棧中已經(jīng)有3這個字面值,便將b直接指向3的地址。這樣,就出現(xiàn)了a與b同時均指向3的情況。
特別注意的是,這種字面值的引用與類對象的引用不同。假定兩個類對象的引用同時指向一個對象,如果一個對象引用變量修改了這個對象的內(nèi)部狀態(tài),那么另一個對象引用變量也即刻反映出這個變化。相反,通過字面值的引用來修改其值,不會導致另一個指向此字面值的引用的值也跟著改變的情況。如上例,我們定義完a與 b的值后,再令a=4;那么,b不會等于4,還是等于3。在編譯器內(nèi)部,遇到a=4;時,它就會重新搜索棧中是否有4的字面值,如果沒有,重新開辟地址存放4的值;如果已經(jīng)有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。
3.2 堆
堆的優(yōu)勢是可以動態(tài)地分配內(nèi)存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數(shù)據(jù)。但缺點是,由于要在運行時動態(tài)分配內(nèi)存,存取速度較慢。
1.存儲的是對象,每個對象都包含一個與之對應(yīng)的class。
2.JVM只有一個堆區(qū)(heap)被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身。
3.對象的由垃圾回收器負責回收,因此大小和生命周期不需要確定。
3.3 方法區(qū)
1.靜態(tài)區(qū),跟堆一樣,被所有的線程共享。
2.方法區(qū)中包含的都是在整個程序中永遠唯一的元素,如class,static變量
字符串常量池則存在于方法區(qū)
字
符串對象的創(chuàng)建 面試題
面試題:String str4 = new String(“abc”) 創(chuàng)建多少個對象?
1、在常量池中查找是否有“abc”對象。
1)有則返回對應(yīng)的引用實例; 2)沒有則創(chuàng)建對應(yīng)的實例對象。
2、在堆中 new 一個 String(“abc”) 對象。
3、將對象地址賦值給str4,創(chuàng)建一個引用。
所以,常量池中沒有“abc”字面量則創(chuàng)建兩個對象,否則創(chuàng)建一個對象,以及創(chuàng)建一個引用。
到此這篇關(guān)于Java數(shù)組與堆棧相關(guān)知識總結(jié)的文章就介紹到這了,更多相關(guān)Java數(shù)組與堆棧內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決IDEA報錯war?exploded?is?not?valid問題
在使用IntelliJ?IDEA時遇到'[projectname]warexploded'無效的問題,可以通過清除項目列表、重新導入項目和配置新的Tomcat來解決,確保在Tomcat配置中,將ApplicationContext修改為僅包含一個'/',這一方法或許能幫助遇到相似問題的開發(fā)者2024-09-09java-servlet-轉(zhuǎn)發(fā)AND路徑(詳解)
下面小編就為大家?guī)硪黄猨ava-servlet-轉(zhuǎn)發(fā)AND路徑(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10Spring實現(xiàn)動態(tài)數(shù)據(jù)源切換的方法總結(jié)
這篇文章主要為大家詳細介紹了一種Spring實現(xiàn)動態(tài)數(shù)據(jù)源切換的方法,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以跟隨小編一起了解一下2023-06-06JAVA使用quartz添加定時任務(wù),并依賴注入對象操作
這篇文章主要介紹了JAVA使用quartz添加定時任務(wù),并依賴注入對象操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09詳解SpringCloud Ribbon 負載均衡通過服務(wù)器名無法連接的神坑
這篇文章主要介紹了詳解SpringCloud Ribbon 負載均衡通過服務(wù)器名無法連接的神坑,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-06-06Java的Cglib動態(tài)代理實現(xiàn)方式詳解
這篇文章主要介紹了Java的Cglib動態(tài)代理實現(xiàn)方式詳解,CGLIB是強大的、高性能的代碼生成庫,被廣泛應(yīng)用于AOP框架,它底層使用ASM來操作字節(jié)碼生成新的類,為對象引入間接級別,以控制對象的訪問,需要的朋友可以參考下2023-11-11