有這么幾種存儲位置呜投,速度逐級遞減:
寄存器
棧內(nèi)存
堆內(nèi)存
靜態(tài)存儲
常量存儲
寄存器是最快的保存區(qū)域饶号,因為它位于和其他所有保存方式不同的地方:處理器內(nèi)部纯趋。然而俏蛮,寄存
器的數(shù)量十分有限桐猬,所以寄存器是根據(jù)需要由編譯器分配麦撵。我們對此沒有直接的控制權(quán),也不可能在自己的
程序里找到寄存器存在的任何蹤跡溃肪。靜態(tài)存儲和常量存儲是存儲使用static定義的各種靜態(tài)數(shù)據(jù)和常量免胃,字符串池也在這。
最重要的是棧內(nèi)存和堆內(nèi)存:
- 棧內(nèi)存:存放基本數(shù)據(jù)類型(8種)和對象句柄(對象的引用惫撰,我喜歡叫對象句柄羔沙,類似于C語言中的指針)。棧指針向下移動則創(chuàng)建空間厨钻,向上移動則釋放空間扼雏,速度幾乎跟寄存器相當(dāng),賊快莉撇。棧內(nèi)存還可以數(shù)據(jù)共享呢蛤,比如說int a=1;int b=1;a創(chuàng)建一塊保存著“1”的存儲空間,當(dāng)創(chuàng)建b時棍郎,b也需要“1”其障,那么棧內(nèi)存就不會創(chuàng)建直接把a的地址給b,這么做的好處不用說是節(jié)約空間涂佃。
-
堆內(nèi)存:存放使用new關(guān)鍵字創(chuàng)建的對象励翼,Java中有垃圾回收機制蜈敢,垃圾回收即對此部分進行回收(回收的是對象內(nèi)存)。堆內(nèi)存最吸引人的地方在于編譯器不必知道要從堆里分配多少存儲空間汽抚,也不必知道存儲的數(shù)據(jù)要
在堆里停留多長的時間抓狭。因此,用堆保存數(shù)據(jù)時會得到更大的靈活性造烁。
了解這些信息就能想通學(xué)習(xí)Java.lang.String對象時碰到的讓我暈乎的問題:
String a1 = "abc";
String a2 = "abc";
System.out.println(a1 == a2); //輸出true
----------------------------------------
String a3 = new String("abc");
String a4 = new String("abc");
System.out.println(a3 == a4); //輸出false
a1句柄創(chuàng)建時在字符串池中創(chuàng)建一個"abc"否过,a2句柄想要一個"abc"常量時,直接把a1的地址給了a2惭蟋,也就是說a1和a2是一模一樣的苗桂,打印true;a3句柄使用new了一個String對象告组,保存在了堆內(nèi)存中煤伟,a4句柄也使用new創(chuàng)建了一個String對象,也保存在了堆內(nèi)存中木缝,兩個句柄分別指向了一個不一樣的堆內(nèi)存的地址便锨,打印出false。
然而又能想到為什么在多次使用String字符串時使用StringBuilder或者StringBuffer來處理字符串了我碟,如果要拼接字符串:
int a = 1;
String a1 = "hello" + a + "w" + a + "orld"....
使用這種方式拼接字符串放案,會在字符串池中創(chuàng)建多個對象,很浪費空間怎囚。
之前面試面試官問我:
String a = new String("123");
會創(chuàng)建幾個對象卿叽,通過閱讀Java編程思想,答案是兩個對象(處在棧內(nèi)存中的a句柄是變量恳守,不屬于對象,處在堆內(nèi)存中的String對象,處在常量池中的"123")贩虾。
再列舉幾個例子:
String a = "123"+"456";//三個
String a1 = "123"; String a2 = "123"; //一個