java變量與內存深入了解


=========================================================================================

    在我看來,學習java最重要是要理解what(這東西是什么),why(為什么要用它),where(在哪用它),how(怎么用)。所以接下來,我都是以這樣的思想來和大家交流,從最基礎的知識講起。如果有啥出錯的,歡迎大家前來批評。本人虛心接納。

=========================================================================================

一.前言

         對於變量,我們再熟悉不過了,誰都知道聲明一個變量,賦值。其實一直以來,變量也並不簡單,我們很少系統地整理分類,更少研究變量對應的儲存結構,這次就深入地了解一下變量,以及常量。

二.What(什么是變量,先從變量說起)

         1.變量的簡單定義:通俗來說,變量就是可以被改變的數據。在程序中聲明變量的語法格式如下: 數據類型 變量名稱= 值  例如:int x= 1,數據類型定義這個變量是什么類型的(有整型,浮點型等),變量名稱只是個別名,值就是對應的數據。

         2.變量的深入定義:由上面可知,變量就是一個可改變的數據,既然是數據,在計算機中肯定有對應的存儲空間來存儲這個數據。也就是說,變量其實就是內存中的一個存儲空間,用來存儲數據。那這么說,聲明一個變量,也就是相當於變量空間的開辟,那么,變量的深入定義還對應上面簡單定義哪些呢?

            (1).聲明一個變量=變量空間的開辟

            (2).變量的數據類型=這個空間要存儲什么數據?

            (3).變量名稱=這個空間叫什么名字?

            (4).變量的值=這個空間的第一次數據是什么?

    那么, 這些變量空間究竟在哪里呢?其實這些變量空間對應計算機內存的堆棧,下面會詳細講解。

         3.變量的分類

            (1).按聲明的位置來分類:

                   a.成員變量:聲明在方法之外的變量,不過沒有 static 修飾。可以不設值,因為有默認值(下面數據類型會有默認值)

                   b.局部變量:聲明在類的方法中的變量。必須對其初始化,否則編譯不過。

                   c.類變量:聲明在方法之外的變量,用 static 修飾

            (2).按數據類型划分(也就是定義數據是什么類型)

                   a.基本數據類型:

                       byte:在內存中占8位(bit),即1個字節,取值范圍-128~127,默認值0

                       short:短整型,在內存中占16位,即2個字節,取值范圍-32768~32717,默認值0

                       int:整型,用於存儲整數,在內在中占32位,即4個字節,取值范圍-2147483648~2147483647,默認值0

                       long:長整型,在內存中占64位,即8個字節-2^63~2^63-1,默認值0L

                       float:浮點型,在內存中占32位,即4個字節,用於存儲帶小數點的數字(與double的區別在於float類型有效小數點只有6~7位),默認值0

                       double:雙精度浮點型,用於存儲帶有小數點的數字,在內存中占64位,即8個字節,默認值0

                       char:字符型,用於存儲單個字符,占16位,即2個字節,取值范圍0~65535,默認值為空

                       boolean:布爾類型,占1個字節,用於判斷真或假(僅有兩個值,即true、false),默認值false

                   注意:整型、實型(常量)、字符型數據可以混合運算。運算中,不同類型的數據先轉化為同一類型,然后進行運算。                

                        轉換從低級到高級:byte,short,char—> int —> long—> float —> double

                         (1).強制類型轉換: 轉換過程中可能導致溢出或損失精度

                                 

                               

                         (2).自動類型轉換:必須滿足轉換前的數據類型的位數要低於轉換后的數據類型,例如: short數據類型的位數為16位,就可以自動轉換位數為32的int類型,同樣float   數據類型的位數為32,可以自動轉換為64位的double類型。       

                         (3).float和double區別:默認的浮點數都是double 只有在數組后邊加上f才是 float的,float f=12.2f;這是定義一個float類型的數據 

                 b.引用數據類型: 除了8中基本類型以外剩下的都是引用類型(類,接口,數組等,后面詳細介紹,new的是引用類型)

                      String:一定要注意,string是引用類型,不是基本類型。

          那么,就有人問了,基本類型和引用類型有啥區別,啥是引用類型,這就有很大學問了,順便也扯上了變量內存結構了。

             (3).詳細講解基本類型和引用類型的區別以及兩者在內存的存儲位置

                  a.上面說過了變量聲明就是一個內存空間的開辟,那這些內存空間在哪呢?

                          首先了解一下java內存結構:JVM分了5片內存:

                          1.程序計數器:記錄程序執行到哪一個指令

                          2.本地方法棧:與虛擬機棧功能相似,不過虛擬機棧為java方法服務,本地方法棧為Native方法服務

                          3.方法區:存放字節碼,常量 ,靜態變量,是一個共享的區域

                          4.虛擬機棧:執行方法其實就是棧幀入棧,出棧的過程,因為是跟方法有關的,而且局部變量常常在方法中,所以棧存儲的是局部變量

               

 

                          5.堆:存放引用類型,成員變量

  注意:(1).我們接觸最多的是堆和棧(虛擬機棧),這里一定要注意這兩個的區別。

          (2).棧主要是存儲方法幀的,每執行一個方法的時候,就會為該方法創建一個棧幀,使其入棧。然而局部變量一般隨着方法生成而存在,所以局部變量存儲在棧中。

         (3).堆一般用來存放引用型對象,以及對應的成員變量,當對象創建時,會在堆中開辟一塊地址,並給這個對象的成員變量使用。

                   b.基本類型沒什么好說的,就是一個空間存儲數.但注意:很多網上教程會說,基本類型是存在棧中,這是錯誤的,因為基本類型也分成員變量和局部變量,局部變量隨着方法入棧就存在棧中,而成員變量會隨着對象在堆中空間的開辟而存儲在堆中。例如: int[] a=new int[]{1,2}; 由於new了一個對象,所以new int[]{1,2}這個對象時存儲在堆中的,也就是說1,2這兩個基本數據類型是存儲在堆中。

                   c.引用類型就比較特別,引用類型占用兩塊內存,一個棧,一個堆, 棧中存放的是堆中的地址。啥意思?什么是引用類型?舉個簡單例子,一間房子,我可以在里面 放置家具,放完后用鑰匙鎖着,把鑰匙放在抽屜里面,那我想找某個家具是不是通過鑰匙來找到房間再進去找家具。從這個例子我們可以對應一下,房間就是內存開辟的空間,家具就是數 據,鑰匙就相當於引用類型(堆中的地址),抽屜相當於,具體的數據放在堆上,引用類型放在棧上。例如:String s=new String("hello world"),new出來的hello world是存放在堆中,並且將這個堆地址給棧中s來保存。

                

 

       (4).變量的作用域:

                  a.從定義上說,變量作用域到大括號結束,出了大括號就就不存在了

                  b.從內存上解釋,一個類中什么時候有大括號的存在?只有兩種情況,一個是類兩端有大括號,例如:public class Person{},還有是類里面的方法有大括號,例如:public void a(){}。先說類里面的方法,上面也說了,執行完這個函數就相當於出棧,那么局部變量也當然隨着函數的結束而銷毀,大括號等同於這個類或方法已經執行完了,也就是說作用域只在大括號內,出了大括號就意味着函數結束了,也就是出棧了,變量作用域就無效了。同理,類兩端里面是全局變量,執行到大括號也就是類被釋放了,對應的全局變量也沒了。

       (5).舉個例子說明一下

           

 

 

         

 

           上面方法執行流程為:

                   1.main方法的棧幀入棧,在main的幀當中有一個a= 20;

                   2.當執行show(a)時,此時傳入了一個參數a= 20;執行show方法,show方法的棧幀入棧,第一次打印結果為a= 20,a改為50,再次打印 結果為:a = 50;

                   3.當執行完show方法后,show方法的棧幀就會出棧;

                   4.此時棧中只有一個main方法的棧幀,所以在執行完show方法后,再去打印a ,此時a = 20;

   三.總結

           1.這篇文章更多是強調變量對應的內存關系,詳細了解堆棧,一定要明確好關系。

            2.引用型基本上都是new出來的,string特別點,引用型new出來的內容放在堆上,地址存放在棧上。

            3.基本類型也分成員變量和局部變量,局部變量隨着方法入棧就存在棧中,而成員變量會隨着對象在堆中空間的開辟而存儲在堆中。

            4.局部變量是存儲在棧中,成員變量是存放在堆中(因為隨着類的創建生成,類創建是在堆上)。

===========================================================================

      用心查閱,有心分享,分享之際,互相指教,受益你我,何樂不為?

 ===========================================================================


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM