2017-09-20 31 views
3

我問了早些時候的問題this並明確了事情。 然而,我有些懷疑,下面說明:陣列聲明並將值分配給陣列中的單個插槽

讓我們假定需要的是具有在此與100個元素的數組:

1)聲明數組:

Integer[] intArr; 

2)分配內存爲100個整數元素並指定變量的參考號

intArr = new Integer[100]; 

現在出現了真正的疑問。

哪一個是分配值到陣列中各個元素的正確方法:

方法1:

intArr[1] = 1; 

方法2:

intArr[1] = new Integer(1); 

我的疑問是,我們已經擁有爲100個元素分配內存,如果我們用戶方法2,我們是不是創建一個更多的內存區域,並將它們分配給intArr 1

intArr [index]是否保存引用的地址或實際對象可以放在intArr [index]中。

希望得到一些見解,以澄清這種疑問。

回答

11

這兩條線有些相同。第一個使用自動裝箱。它實際上直接等同於:

intArr[1] = Integer.valueOf(1); 

不同的是,這可以重用引用同一個Integer對象多次,而在你的第二個辦法,你要創建一個新的Integer對象。你可以在這裏看到區別:

intArr[1] = Integer.valueOf(1); 
intArr[2] = Integer.valueOf(1); 
System.out.println(intArr[1] == intArr[2]); // True, references to the same object 

intArr[1] = new Integer(1); 
intArr[2] = new Integer(1); 
System.out.println(intArr[1] == intArr[2]); // False, references to the different objects 

在所有情況下,數組的值都是引用。它們本身從來不是物體。當您分配陣列時,爲100 引用創建足夠的空間,並且這些引用最初都是null

如果你想包含整數數據數組直接,只是使用的int[]代替Integer[]

+0

*這兩行大致相同*功能上。但實際上,直接調用Integer構造函數的原因很少。 – shmosel

+0

@shmosel:是的 - 因此下面的段落。 (我「廣泛地」改爲「稍微」) –

+0

非常感謝幫助解決這個疑問,清除了它。 – CuriousMind

5

我的疑問是,我們已經爲100個元素分配了內存,如果我們用戶方法2,我們是不是創建一個更多的內存區域並將其分配給intArr1?

您在new Integer[100]中分配的內存用於數組將包含的100個對象引用,而不是其包含的對象。當添加到數組中時,由於它是一個對象數組,因此您仍然必須創建該對象。

你的方法其實本質上是幕後相同,因爲編譯器會自動「盒子」,通過Integer.valueOf(1)1的方法1,更改:

intArr[1] = 1; 

intArr[1] = Integer.valueOf(1); 

(即使不依靠自動裝箱,Integer.valueOf通常是獲得Integer實例的更好方法,因爲它可以緩存它們[並且始終緩存實例,以便從-128到127]。)

讓我們跟隨它通過與一些ASCII藝術:

當你這樣做:

Integer[] intArr; 

你有記憶是這樣的:

 
intArr[null] 

例如,含有null變量。現在你分配的內存陣列,並將其賦值給變量:

intArr = new Integer[100]; 

,你會得到這樣的事情:

 
        +−−−−−−−−−−−−−−−−+ 
intArr[Ref21345]−−−−>| Integer[100] | 
        +−−−−−−−−−−−−−−−−+ 
        | 0: null  | 
        | 1: null  | 
        | ...   | 
        | 99: null  | 
        +−−−−−−−−−−−−−−−−+ 

現在我們有空間來存儲100所對象引用;他們都從null開始。然後,你做:

intArr[0] = 1; 

,編譯器變成

intArr[0] = Integer.valueOf(1); 

,你會得到:

 
        +−−−−−−−−−−−−−−−−+ 
intArr[Ref21345]−−−−>| Integer[100] | 
        +−−−−−−−−−−−−−−−−+  +−−−−−−−−−−+ 
        | 0: [Ref84651] |−−−−>| Integer | 
        | 1: null  |  +−−−−−−−−−−+ 
        | ...   |  | value: 1 | 
        | 99: null  |  +−−−−−−−−−−+ 
        +−−−−−−−−−−−−−−−−+ 
+1

非常感謝您的詳細解答,幫助我們解決疑惑。 – CuriousMind

+0

這些ASCII圖表太甜美了:D。手工製作還是任何工具? –

+1

@ꜱᴜʀᴇꜱʜᴀᴛᴛᴀ:用vim手工製作。 –

1

只是爲了闡述。

如果你說

int[] vals = new int[10]; 

你是10點的整數分配空間。這意味着這裏分配的內存是10* 32位。

Integer[] vals = new Integer[10]. 

這裏分配的內存是空的(除了數組對象本身)。數組內的所有元素都是null,並且不會攜帶任何內存。

所以,當你做

intArr[1] = new Integer(1); 

內存分配給new Integer(1)和參考被賦予的intArr索引,所以你實際上是分配內存只有一次。

即使你正在做的

intArr[1] = 1; 

它實際上是自動裝箱爲Integer並存儲參考。