java中記憶體分配以及static的用法
Java記憶體分配與管理是Java的核心技術之一,一般Java在記憶體分配時會涉及到以下區域:
1.棧區:由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。
2.堆區:由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收 。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列。
3.全域性區(靜態區):全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。程式結束後由系統釋放。
4.文字常量區:常量字串就是放在這裡的,程式結束後由系統釋放 。
5.程式程式碼區
堆疊記憶體的分配
棧區:區域性變數存在棧記憶體中。函式的引數值也存放著棧區。儲存類的例項,即堆區物件的引用(指標)。
堆:用來存放動態產生的資料,比如new出來的物件。注意創建出來的物件只包含屬於各自的成員變數,並不包括成員方法。因為同一個類的物件擁有各自的成員變數,儲存在各自的堆中,但是他們共享該類的方法,並不是每建立一個物件就把成員方法複製一次。常量池存在於堆記憶體。
程式碼:package string;
public class memonry {
/** * @param args * a1和a2是區域性變數,放在棧區,而new出的物件放在堆區,堆區還有某類的成員變數 */ public static void main(String[] args) { // TODO Auto-generated method stub a a1=new a(); a1.a=1; a1.b="asd"; a a2=new a(); a2.a=2; a2.b="a2"; }
}
class a{
int a;
String b;
}
如果另a2=a1;則圖就變成如下所示
原因:a2=a1將a1指向堆的地址給了a2,即a2也指向了a1的堆地址。這樣原來的那個a2指向的記憶體就變成java中所謂的垃圾了,就會被jvm垃圾回收機制所回收。
static的用法:
靜態static:靜態會在堆記憶體建立一個靜態記憶體區。靜態有:靜態屬性,靜態方法,靜態類。而靜態方法不能呼叫非靜態資料,
因為靜態屬性依賴於類,而不是物件。而非靜態依賴於物件,靜態類一旦建立,只會有一個,並且在該類中是共享的。一但使用
靜態屬性,那麼就會自動賦一個值,比如int型的話預設就為0,boolean的就為false,string就為null。如:某個類中有靜態屬
性時,不應該new一個物件去操作該屬性,而是應該直接使用該類名去操作他。
使用static的優點:
1.一個靜態屬性在堆記憶體只能存在一個,即大家可以共享該屬性值。
2.如果一個物件陣列中其中的某人屬性大家都是相同的,即可以使用靜態,這樣可以節省記憶體空間。
3.靜態一旦建立,生命週期就會從建立開始到該程式結束才會死亡。
4.靜態依賴於類,而不是物件。
程式碼:
public class Static {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
c.number=12;//通過類名直接更改靜態屬性,
c c1=new c();
//c.number=11;//這樣也可以,但會給人錯覺,認為是物件去操作該靜態類,所以不提倡這種寫法。
c1.a();
c.b();
c.c=122;
c.b();
}
}
class c{
public static int c;
static boolean a;
static int number;
String name;
public void a(){
System.out.println(number);
System.out.println(c);
}
public static void b(){
//System.out.println(name);//因為name為非靜態屬性,而該方法為靜態方法,所以無法呼叫該屬性。
System.out.println(a);
System.out.println(c);
}
}