Java中內存,成員變量,局部變量

一 java內存分配

這裏只是在網上找的一些資料;
Java 中的數據類型分爲
1. 基本類型(原始數據類型) byte short int long float double char boolean
基本類型的變量持有原始值。
2. 符合數據類型(引用類型),引用類型持有引用值(即對某個對象的引用,而非對象本身)。

一般Java在內存分配時會涉及到以下區域:
1. 寄存器:我們在程序中無法控制
2. 棧:存放基本類型的數據和對象的引用但對象本身不存放在棧中,而是存放在堆中
3. 堆:存放用new產生的數據
4. 靜態域:存放在對象中用static定義的靜態成員
5. 常量池:存放常量
6. 非RAM存儲:硬盤等永久存儲空間
其中主要是堆,棧的存儲。

堆,棧

  1. 函數中定義的一些基本類型的數據變量對象的引用變量都在函數的棧內存中分配。
    棧的優勢是存取速度比堆要快,僅次於直接位於CPU 的寄存器,而且數據可以共享
    存在棧中的數據大小與生存週期必須是確定的。因此裏面的變量通常是局部變量、函數參數等。
    當在一段代碼塊定義一個變量時(局部變量),Java就在棧中 爲這個變量分配內存空間,當該變量退出該作用域後,Java會自動釋放掉爲該變量所分配的內存空間,該內存空間可以立即被另作他用。

  2. 堆內存用來存放由new創建的對象和數組。 在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。

在堆中產生了一個數組或對象後,還可以 在棧中定義一個特殊的變量,讓棧中這個變量的取值等於數組或對象在堆內存中的首地址,棧中的這個變量就成了數組或對象的引用變量。
引用變量是普通的變量,定義時在棧中分配,引用變量在程序運行到其作用域之外後被釋放。而數組和對象本身在堆中分配,即使程序 運行到使用 new 產生數組或者對象的語句所在的代碼塊之外,數組和對象本身佔據的內存不會被釋放,數組和對象在沒有引用變量指向它的時候,才變爲垃圾,不能在被使用,但仍 然佔據內存空間不放,在隨後的一個不確定的時間被垃圾回收器收走(釋放掉)。

棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變量的存儲區。裏面的變量通常是局部變量、函數參數等。

堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那麼在程序結束後,操作系統會自動回收。

二 成員變量,局部變量

class A 
{ 
int a;//成員變量 
public static void main(String[] args) 
{ 
//類變量
static int c;
int b;//局部變量 
} 
}

成員變量:作爲類的成員而存在,直接存在於類中。

類變量:static 修飾,靜態變量存儲在方法區。

局部變量:方法內部,塊內部都是局部,執行指令退出那個局部,局部變量自動清除。

1.成員變量可以被public,protect,private,static等修飾符修飾,而局部變量不能被控制修飾符及static修飾;兩者都可以定義成final型

2.成員變量存儲在堆,局部變量存儲在棧

3.存在時間不同

4.成員變量有默認值,(被final修飾且沒有static的必須顯式賦值),局部變量不會自動賦值,局部變量在使用前必須被程序員主動的初始化,然後才能使用。

看下面對比成員變量局部變量:

public class Variable { 
int i; 
void test() { 
   int j=8; 
   if(j==i) 
    System.out.println("相等"); 
   else 
    System.out.println("不相等"); 
} 
public static void main(String[] args) { 
   Variable v=new Variable(); 
   v.test(); 
} 
}

程序二:

public class Variable { 
   void test() { 
   int i; 
   int j=8;
   //這裏 i 被使用了,但是還沒有賦值,所以報錯 
   if(j==i) 
    System.out.println("相等"); 
   else 
    System.out.println("不相等"); 
} 
public static void main(String[] args) 
{ 
   Variable v=new Variable(); 
   v.test(); 
} 
}

第一個程序很正常,編譯時不會出錯。第二個程序編譯時會錯誤,因爲局部變量沒有初始化。成員變量有默認值,(被final修飾且沒有static的必須顯式賦值),局部變量不會自動賦值

public static int transeInt(String s){

        //digit不會報錯,result 會報錯
        int digit;
        int result;

        if(s.length()==0||s==null)
            System.out.println("錯誤字符串");

        for(int i=0;i<s.length();i++){
            //這裏digit被顯示的賦值了(所以不一定是創建之後就被賦值)
            digit = s.charAt(i)-'0';
            //result*10   還未被賦值就被使用了,所以報錯
            result = result*10+digit;
        }

        return result;
    }

參考:http://www.360doc.com/content/10/1002/21/2088355_58009874.shtml
http://my.oschina.net/u/201253/blog/37324

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章