8     參考資料型別和基本資料型別大不同

參考資料型別是Java程式語言的重心,因效率問題Java不使用new指令產生基本資料型別的物件,致使Java納入了非物件(non-object)元素。兩種資料型別的相異處如下:

(1)程式執行時的記憶體存放位置

基本資料型別存放於名為Stack的記憶體區塊,各基本型別因資料長度較小且固定,存放於效率較高的Stack區塊。

參考資料型別存放於名為Heap的記憶體區塊,需使用new指令產生的物件皆存放於此,此區塊記憶體處理效率較Stack區塊為差。

(2)變數資料內容

基本資料型別屬實值型別,變數存放的是實際的值,參考資料型別存放的是參考,也就是物件的位址。

(3)運算結果相異

因為參考資料型別變數存放的是位址,變數經過指定運算(=)後,人們對其後續的運算所期待的結果,和實際上的結果有所出入,也就是說和基本資料型別的運算結果是不同的。有關這一點必須理解清楚,下面將舉例說明之。

(註:Java真的有點難度,同屬參考資料型別的String又和其他物件型別不同,將另闢專章討論,此處僅對自建類別物件舉例。)

 

<基本型別的指定運算(賦值)>基本資料型別

public class PriType{

   public static void main(String[] args){

     int i1 = 222;

     int i2 = 333;

 

     System.out.println("i1i2初期值:");

     System.out.println("i1 = " + i1);

     System.out.println("i2 = " + i2);

 

     i2 = i1;

     System.out.println("i2 = i1指定運算後:");

     System.out.println("i1 = " + i1);

     System.out.println("i2 = " + i2);

 

     i1 = 111;

     System.out.println("i1=111更改內容後:");

     System.out.println("i1 = " + i1);

     System.out.println("i2 = " + i2);

   }

}

 

 

執行結果:C:\js>java PriType

i1i2初期值:

i1 = 222

i2 = 333

i2 = i1指定運算後:

i1 = 222

i2 = 222

i1=111更改內容後:

i1 = 111

i2 = 222

 

<資料遷移圖示>

Stack

i1=222

i2=333

 

   s2=s1

 

Stack

i1=222

i2=222

 

   s1=111

 

Stack

i1=111

i2=222

 

  

 

<參考型別的指定運算(賦址)>自建類別物件

class StringA{

String mos = new String();

}

 

public class RefType{

   public static void main(String[] args){

     StringA s1 = new StringArray ();

     StringA s2 = new StringArray ();

     s1.mos = "男人比女人更容易招惹蚊子";

     s2.mos = "物體愈黑,蚊子愈感興趣";

 

     System.out.println("s1.moss2.mos初期值:");

     System.out.println("s1.mos = " + s1.mos);

     System.out.println("s2.mos = " + s2.mos);

 

     s2 = s1;

     System.out.println("s2 = s1指定運算後:");

     System.out.println("s1.mos = " + s1.mos);

     System.out.println("s2.mos = " + s2.mos);

 

     s1.mos = "大人比小孩更容易被蚊子咬";

     System.out.println("s1更改內容後:");

     System.out.println("s1.mos = " + s1.mos);

     System.out.println("s2.mos = " + s2.mos);

   }

}

執行結果:C:\js>java RefType

s1.moss2.mos初期值:

s1.mos = 男人比女人更容易招惹蚊子

s2.mos = 物體愈黑,蚊子愈感興趣

s2 = s1指定運算後:

s1.mos = 男人比女人更容易招惹蚊子

s2.mos = 男人比女人更容易招惹蚊子

s1更改內容後:

s1.mos = 大人比小孩更容易被蚊子咬

s2.mos = 大人比小孩更容易被蚊子咬

 

<資料遷移圖示>

Stack

                    

Heap

s1位址a1

a1

mos="男人比女人更容易招惹蚊子"

s2位址a2

a2

mos="物體愈黑,蚊子愈感興趣"

         

 

↓   s2=s1

 

Stack

 

Heap

s1位址a1

a1

mos="男人比女人更容易招惹蚊子"

s2位址a1

a2

mos="物體愈黑,蚊子愈感興趣"

         

 

↓   s1.mos = "大人比小孩更容易被蚊子咬"

 

Stack

 

Heap

s1位址a1

a1

mos="大人比小孩更容易被蚊子咬"

s2位址a1

a2

mos="物體愈黑,蚊子愈感興趣"

         

 

s2指定為s1運算(s2=s1)後,因參考型別變數內容為位址,故指向同一位址的物件,s1s2mos內容是同一個了,之後更改了s1mos內容,也就等於改了s2mos內容。

因沒任何物件指向虛線無色的a2位址記憶體區塊,會成為系統GC(garbage collector)記憶體清理回收的對象,回收後可供給其他物件使用。

arrow
arrow

    祈泊 發表在 痞客邦 留言(0) 人氣()