Ⅰ java基本數據類型在棧中怎麼存放的
1、所有餘悶正的基本數據類型全部是存儲在棧裡面,速度快。2、一個對象,它的實體是存儲在堆裡面的,而它的引用是存儲在棧裡面。
2
例子:String str = new String("123");這個str就在棧裡面,而他的"123"這個對象在堆裡面。 str 指向"123";3、就對象本身而言,它的所有屬性的值如果不是單例或者靜態的,就是存儲在堆裡面的。一豎悔個罩顫類的所有對象的屬性值都在堆裡面 並且佔用不同的內存空間,而一個類的方法只在方法區里佔一個地方,所有的對象指向同一個方法區。
Ⅱ java 中 的 堆 和 棧 有 什 么 區 別 要 詳 細 點 的 !
java中堆(heap)和堆棧(stack)有什麼區別 stack 和 heep 都是內存的一部分
stack 空間小,速度比較快, 用來放對象的引用
heep 大,一般所有創建的對象都放在這里。
棧(stack):是一個先進後出的數據結構,通常用於保存方法(函數)中的參數,局部變數.
在java中,所有基本類型和引用類型都在棧中存儲.棧中數據的生存空間一般在當前scopes內(就是由{...}括起來的區域).
堆(heap):是一個可動態申請的內存空間(其記錄空閑內存空間的鏈表由操作系統維護),C中的malloc語句所產生的內存空間就在堆中.
在java中,所有使用new xxx()構造出來的對象都在堆中存儲,當垃圾回收器檢測到某對象未被引用,則自動銷毀該對象.所以,理論上說java中對象的生存空間是沒有限制的,只要有引用類型指向它,則它就可以在任意地方被使用.
1. 棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。
2. 棧的優勢是,存取速度比堆要快,僅次於直接位於CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。另外,棧數據可以共享,詳見第3點。堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由於要在運行時動態分配內存,存取速度較慢。
3. Java中的數據類型有兩種。
一種是基本類型(primitive types), 共有8種,即int, short, long, byte, float, double, boolean, char(注意,並沒有string的基本類型)。 這種類型的定義是通過諸如int a = 3; long b = 255L;的形式來定義的,稱為自動變數。值得注意的是,自動變數存的是字面值,不是類的實例,即不是類的引用,這里並沒有類的存在。如int a = 3; 這里的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數據,由於大小可知,生存期可知(這些字面值固定定義在某個程序塊裡面,程序塊退出後,欄位值就消失了),出於追求速度的原因,就存在於棧中。
另外,棧有一個很重要的特殊性,就是存在棧中的數據可以共享。假設我們同時定義:
int a = 3;
int b = 3;
編譯器先處理int a = 3;首先它會在棧中創建一個變數為a的引用,然後查找有沒有字面值為3的地址,沒找到,就開辟一個存放3這個字面值的地址,然後將a指向3的地址。接著處理int b = 3;在創建完b的引用變數後,由於在棧中已經有3這個字面值,便將b直接指向3的地址。
這樣,就出現了a與b同時均指向3的情況。特別注意的是,這種字面值的引用與類對象的引用不同。
假定兩個類對象的引用同時指向一個對象,如果一個對象引用變數修改了這個對象的內部狀態,那麼另一個對象引用變數也即刻反映出這個變化。
相反,通過字面值的引用來修改其值,不會導致另一個指向此字面值的引用的值也跟著改變的情況。 如上例,我們定義完a與b的值後,再令a=4;那麼,b不會等於4,還是等於3。在編譯器內部,遇到a=4;時,它就會重新搜索棧中是否有4的字面值,如果沒有,重新開闢地址存放4的值;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。
另一種是包裝類數據,如Integer, String, Double等將相應的基本數據類型包裝起來的類。這些類數據全部存在於堆中,Java用new()語句來顯示地告訴編譯器,在運行時才根據需要動態創建,因此比較靈活,但缺點是要佔用更多的時間。
4.String是一個特殊的包裝類數據。即可以用String str = new String("abc");的形式來創建,也可以用String str = "abc";的形式來創建(作為對比,在JDK 5.0之前,你從未見過Integer i = 3;的表達式,因為類與字面值是不能通用的,除了String。而在JDK 5.0中,這種表達式是可以的!因為編譯器在後台進行Integer i = new Integer(3)的轉換!)。
前者是規范的類的創建過程,即在Java中,一切都是對象,而對象是類的實例,全部通過new()的形式來創建。Java中的有些類,如DateFormat類,可以通過該類的getInstance()方法來返回一個新創建的類,似乎違反了此原則。其實不然。該類運用了單例模式來返回類的實例,只不過這個實例是在該類內部通過new()來創建的,而getInstance()向外部隱藏了此細節。那為什麼在String str = "abc";中,並沒有通過new()來創建實例,是不是違反了上述原則?其實沒有。
5. 關於String str = "abc"的內部工作。Java內部將此語句轉化為以下幾個步驟:
(1)先定義一個名為str的對String類的對象引用變數:String str;
(2)在棧中查找有沒有存放值為"abc"的地址,如果沒有,則開辟一個存放字面值為"abc"的地址,接著創建一個新的String類的對象o,並將o的字元串值指向這個地址,而且在棧中這個地址旁邊記下這個引用的對象o。如果已經有了值為"abc"的地址,則查找對象o,並返回o的地址。
(3)將str指向對象o的地址。
值得注意的是,一般String類中字元串值都是直接存值的。但像String str = "abc";這種場合下,其字元串值卻是保存了一個指向存在棧中數據的引用!
為了更好地說明這個問題,我們可以通過以下的幾個代碼進行驗證。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
注意,我們這里並不用str1.equals(str2);的方式,因為這將比較兩個字元串的值是否相等。==號,根據JDK的說明,只有在兩個引用都指向了同一個對象時才返回真值。而我們在這里要看的是,str1與str2是否都指向了同一個對象。
結果說明,JVM創建了兩個引用str1和str2,但只創建了一個對象,而且兩個引用都指向了這個對象。
我們再來更進一步,將以上代碼改成:
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發現在棧中沒有存放該值的地址,便開辟了這個地址,並創建了一個新的對象,其字元串的值指向這個地址。
事實上,String類被設計成為不可改變(final)的類。如果你要改變其值,可以,但JVM在運行時根據新值悄悄創建了一個新對象,然後將這個對象的地址返回給原來類的引用。這個創建過程雖說是完全自動進行的,但它畢竟佔用了更多的時間。在對時間要求比較敏感的環境中,會帶有一定的不良影響。
再修改原來代碼:
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並沒有創建新對象)。當str1改完其值後,再創建一個String的引用str4,並指向因str1修改值而創建的新的對象。可以發現,這回str4也沒有創建新的對象,從而再次實現棧中數據的共享。
我們再接著看以下的代碼。
String str1 = new String("abc");
String str2 = "abc";
System.out.println(str1==str2); //false
創建了兩個引用。創建了兩個對象。兩個引用分別指向不同的兩個對象。
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1==str2); //false
創建了兩個引用。創建了兩個對象。兩個引用分別指向不同的兩個對象。
以上兩段代碼說明,只要是用new()來新建對象的,都會在堆中創建,而且其字元串是單獨存值的,即使與棧中的數據相同,也不會與棧中的數據共享。
6. 數據類型包裝類的值不可修改。不僅僅是String類的值不可修改,所有的數據類型包裝類都不能更改其內部的值。
7. 結論與建議:
(1)我們在使用諸如String str = "abc";的格式定義類時,總是想當然地認為,我們創建了String類的對象str。擔心陷阱!對象可能並沒有被創建!唯一可以肯定的是,指向String類的引用被創建了。至於這個引用到底是否指向了一個新的對象,必須根據上下文來考慮,除非你通過new()方法來顯要地創建一個新的對象。因此,更為准確的說法是,我們創建了一個指向String類的對象的引用變數str,這個對象引用變數指向了某個值為"abc"的String類。清醒地認識到這一點對排除程序中難以發現的bug是很有幫助的。
(2)使用String str = "abc";的方式,可以在一定程度上提高程序的運行速度,因為JVM會自動根據棧中數據的實際情況來決定是否有必要創建新對象。而對於String str = new String("abc");的代碼,則一概在堆中創建新對象,而不管其字元串值是否相等,是否有必要創建新對象,從而加重了程序的負擔。
(3)當比較包裝類裡面的數值是否相等時,用equals()方法;當測試兩個包裝類的引用是否指向同一個對象時,用==。
(4)由於String類的final性質,當String變數需要經常變換其值時,應該考慮使用StringBuffer類,以提高程序效率。
Ⅲ 用java實現數據結構「棧
Java棧的實現
public class MyStack { //定義一個堆棧類
int[] array; //用int數組來保存數據,根據需要可以換類型
int s_size; //定義堆棧的寬度
public MyStack(int i){ //定義一個帶參數構造器
array=new int[i]; //動態定義數組的長度
s_size=0; //堆棧的默認寬度為0
}
public MyStack(){ //默認構造器
this(50); //默認構造器可容納50個元素
}
public void push(int i){ //壓棧
array[this.s_size]=i;
this.s_size++;
}
public int pop(){ //從堆棧中取元素,從棧頂開始取
if(this.s_size!=0){
int t=array[s_size-1]; //用中間變數保存棧頂的元素
array[s_size-1]=0; //取完元素該位置設為0
s_size--; //棧的大小減1
return t; //返回棧頂元素
}else{
System.out.println("This stack is empty"); //當棧為空時顯示提示信息,返回0
return 0;
}
}
public boolean isEmpty(){ //判斷棧是否為空
return this.s_size==0;
}
public int top(){ //從棧頂取值,功能和 pop() 方法一樣
if(!this.isEmpty()){
int t=array[this.s_size-1];
array[this.s_size-1]=0;
this.s_size--;
return t;
}else{
System.out.println("This stack is empty!");
return 0;
}
}
public void printAll(){ //列印出堆棧中的所有元素的值,不是取出,元素依然在堆棧里
if(!this.isEmpty()){
for(int i=this.s_size - 1;i>=0;i--){
System.out.println(array[i]);
}
}
}
//下面是測試代碼
public static void main(String[] args){
MyStack stack=new MyStack();
stack.push(4);
stack.push(5);
stack.push(6);
stack.push(7);
//System.out.println(stack.isEmpty());
stack.printAll();
System.out.println("===========");
System.out.println(stack.top());
System.out.println(stack.top());
System.out.println(stack.top());
System.out.println(stack.top());
System.out.println(stack.top());
}
}
Ⅳ 請簡單通俗易懂的解釋一下在Java中什麼叫堆 什麼叫棧 謝謝
堆:也叫動態內存,相當於一個內存池子,在java中創建對象的時候,就從堆裡面拿出一塊來存放對象;當GC(垃圾回收)回收對象的時候,又把對象佔用的內容還給堆。
舉個例子:堆就好比一個面團,類就好比一個饅頭印子,用印子從面團中取出一小塊面團,印成饅頭,這個饅頭就是這個饅頭印子類產生的對象了。當無限的創建饅頭的時候,這個面團總會被用光的,這個時候就不能在創建新的饅頭了。
所有GC就有存在的必要了,當對象不被持有的時候,GC就會把對象還給堆。也就是,當這個饅頭沒有被使用,這個饅頭就變成小面團,還給面團。
棧:也是一段內存,但是這段內存比較有特點,遵循一個先進後出的規則。
舉個例子:吃過罐裝的薯片吧,薯片一片一片的放到罐裡面去,想想,最先放進去的是不是放在罐的最底部。現在一片片把薯片取出來,是不是要從最頂部開始去,也就是最後放進去的,最先取出來。這個薯片放進去和取出來的這個過程,就是棧的工作原理啦(先進入的後出來,後進入的先出來)
在java中的棧:棧的原理明白了,其實只要是計算機只要是編程語言,什麼堆什麼棧都是一樣的,基本作用也一樣。java中可以認為,棧用來存放局部變數的。
public void fun(){
int i=0; //i 是一個局部變數,存放在棧裡面的
Object obj = new Objec(); //obj 是一個對象應用,同樣也是一個局部變數,存放在站裡面的,但是obj指向的對象,在存在堆中
}
Ⅳ Java棧和本地方法棧方法調用棧,這些都是什麼
JAVA內存裡面有一般有四個分類,堆,
棧(堆棧),
靜態域,
常量池
棧:
實際上是一個隊列,
遵循
FILO的原則(後進先出),
裡面儲存的是函數的參數值,局部變數,對象的引用(對象本身不在這里)等,因此在每調用一個函數時,堆棧都會分配一部分空間給它,函數返回時,被釋放
堆:
儲存靜態變數,全局變數
和
用new創建的東西,棧中的內存是動態內存,其中的內存在不使用時隨時可以被回收
靜態域:存放對象中static定義的成員
常量池:存放常量
根據以上解釋回答你的問題:
JAVA棧存的是函數的參數值,局部變數,對象的引用
方法調用棧?
沒有這說法吧,
方法的調用是存在棧中的
本地方法棧,
和JAVA中的棧一個作用,
只是這個棧是屬於本地的,不屬於JAVA虛擬機,但受JAVA虛擬機的控制,因為是JAVA虛擬機簡單地動態鏈接並直接調用指定的本地方法。可以把這看作是虛擬機利用本地方法來動態擴展自己
局部變數和對象引用存在
棧
中,
方法調用的棧幀也是在
棧
中
以上是我自己查資料+自己的理解,有錯望指出
Ⅵ java中什麼是棧啊
存放基本類型的變數數據和對象的引用,但對象本身不存放在棧中,而是存放在堆(new 出來的對象)或者常量池中(字元串常量對象存放在常量池中。)。
棧和常量池中的對象可以共享,對於堆中的對象不可以共享。棧中的數據大小和生命周期是可以確定的,當沒有引用指向數據時,這個數據就會消失。堆中的對象的由垃圾回收器負責回收,因此大小和生命周期不需要確定。
局部變數的數據存在於棧內存中。
棧的優勢是,存取速度比堆要快,僅次於寄存器,棧數據可以共享。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。棧中主要存放一些基本類型的變數數據(int, short, long, byte, float, double, boolean, char)和對象句柄(引用)。
Ⅶ 我要用java實現一個棧,基本操作就是出棧入棧。請問如何實現效率比較高。
java的list的子類裡面有個叫vector,這個下面有個叫做stack,可以實現!你去看 看看
Ⅷ java中什麼是棧啊
棧是一種常用的數據結構,棧只允許訪問棧頂的元素,棧就像一個杯子,每次都只能取杯子頂上的東西,而對於棧就只能每次訪問它的棧頂元素,從而可以達到保護棧頂元素以下的其他元素.」先進後出」或」後進先出」就是棧的一大特點,先進棧的元素總是要等到後進棧的元素出棧以後才能出棧.遞歸就是利用到了系統棧,暫時保存臨時結果,對臨時結果進行保護.
對於棧的學習,建議你看一看<數據結構與演算法>這本書.
Ⅸ Java棧和本地方法棧方法調用棧,這些都是什麼
JAVA內存裡面有一般有四個分類,堆, 棧(堆棧), 靜態域, 常量池
棧: 實際上是一個隊列, 遵循 FILO的原則(後進先出), 裡面儲存的是函數的參數值,局部變數,對象的引用(對象本身不在這里)等,因此在每調用一個函數時,堆棧都會分配一部分空間給它,函數返回時,被釋放
堆: 儲存靜態變數,全局變數 和 用new創建的東西,棧中的內存是動態內存,其中的內存在不使用時隨時可以被回收
靜態域:存放對象中static定義的成員
常量池:存放常量
根據以上解釋回答你的問題:
JAVA棧存的是函數的參數值,局部變數,對象的引用
方法調用棧? 沒有這說法吧, 方法的調用是存在棧中的
本地方法棧, 和JAVA中的棧一個作用, 只是這個棧是屬於本地的,不屬於JAVA虛擬機,但受JAVA虛擬機的控制,因為是JAVA虛擬機簡單地動態鏈接並直接調用指定的本地方法。可以把這看作是虛擬機利用本地方法來動態擴展自己
局部變數和對象引用存在 棧 中, 方法調用的棧幀也是在 棧 中
以上是我自己查資料+自己的理解,有錯望指出