簡體   English   中英

使用 Java Arrays.fill(array,int[] subArray) 時,為什么 subArray 共享同一個 memory 塊?

[英]When using Java Arrays.fill(array,int[] subArray), why subArray share the same memory block?

int[][] dp = new int[5][2];
Arrays.fill(dp,new int[]{2,3});
dp[1][0] = 10;

我以為只有 dp[1][0] 改為 10,但所有 dp[x][0] 都是 10(x 是從 0 到 4)。 我發現了一條與我的問題相關的評論,“這一行使每一行都引用同一個 memory 塊,即更改 arr[1][5] 也會更改 arr[100][5]。” 那么為什么這些數組對象共享相同的 memory 呢? 它們都在 JVM 堆還是常量池中?

相關鏈接: https://stackoverflow.com/a/19199560/13724489

你會認為Array.fill(dp, new int[2]{2,3})相當於:

dp[0] = new int[2]{2,3};
dp[1] = new int[2]{2,3};
dp[2] = new int[2]{2,3};
dp[3] = new int[2]{2,3};
dp[4] = new int[2]{2,3};

但不,它更像是:

int[] val = new int[2]{2,3};
dp[0] = val;
dp[1] = val;
dp[2] = val;
dp[3] = val;
dp[4] = val;

您只會在Array.fill(dp, new int[2]{2,3})行中創建一個數組。 dp中的所有子數組都引用您創建的單個數組。 dp[0]dp[1]dp[whatever]都指向同一個數組。

這是因為當你調用一個方法時,所有的 arguments 在方法運行之前都會被評估,所以new int[2]{2,3}在調用fill之前被評估。 fill不會在循環中“運行”表達式new int[2]{2,3}並將其分配給數組。 fill甚至不知道您使用了什么表達式,而是僅知道表達式new int[2]{2,3}計算的值 - 對一個新創建的 int 數組fill的引用。 fill然后將相同的 object 分配給dp的每個索引。

他們說的是真的:

    int[][] dp = new int[5][2];
    Arrays.fill(dp, new int[] { 2, 3 });
    dp[1][0] = 10;
    
    System.out.println(Arrays.deepToString(dp));

Output:

[[10, 3], [10, 3], [10, 3], [10, 3], [10, 3]]

在代碼中,您只實例化了一個int[] (一個一維整數數組)。 您只執行一次new int[] { 2, 3 }) 所以你只有一個內部數組。 fill方法將對該相同數組的引用填充到外部數組的每個槽中。 這就是發生的事情。

另外兩點

  1. 正如 Holger 在評論中所說,當我們之后構造內部數組時,在聲明中也構造它們是一種浪費。 省略內部維度以首先僅構造外部數組:

     int[][] dp = new int[5][]; // No number in the second set of square brackets
  2. 順便說一句,您在這行代碼中有一個錯誤:

     Arrays.fill(dp,new int[2]{2,3});

    您不能同時給出數組維度(長度)內容。 在我的 Eclipse 中,我得到Cannot define dimension expressions when an array initializer is provided 因此,就像我在上面所做的那樣,將方括號中的2省略掉。

如果你想要五個獨立的內部 arrays ,你可以使用setAll方法:

    Arrays.setAll(dp, index -> new int[] { 2, 3 });

現在 output 將是:

[[2, 3], [10, 3], [2, 3], [2, 3], [2, 3]]

現在發生的是setAll為外部數組的每個索引調用new int[] { 2, 3 } ,因此創建了五個內部 arrays。

當你運行int[][] dp = new int[5][2]; ,你得到一個長度為 5 的外部數組,和 5 個長度為 2 的內部 arrays。所有 5 個內部 arrays 都填充了0值。

dp →→→┌───┐   ┌───┬───┐
      │ •→│→→→│ 0 │ 0 │
      ├───┤   └───┴───┘ ┌───┬───┐
      │ •→│→→→→→→→→→→→→→│ 0 │ 0 │
      ├───┤   ┌───┬───┐ └───┴───┘
      │ •→│→→→│ 0 │ 0 │
      ├───┤   └───┴───┘ ┌───┬───┐
      │ •→│→→→→→→→→→→→→→│ 0 │ 0 │
      ├───┤   ┌───┬───┐ └───┴───┘
      │ •→│→→→│ 0 │ 0 │
      └───┘   └───┴───┘

然后運行Arrays.fill(dp,new int[2]{2,3}); ,您創建一個長度為 2 且值為23的新數組,然后使用對該新數組的引用填充外部數組的所有 5 個位置。 前5個內部arrays被丟棄:

dp →→→┌───┐                  ┌───┬───┐
      │ •→│→→→→→↓            │ 0 │ 0 │
      ├───┤     ↓            └───┴───┘ ┌───┬───┐
      │ •→│→→→↓ ↓                      │ 0 │ 0 │
      ├───┤   ┌───┬───┐      ┌───┬───┐ └───┴───┘
      │ •→│→→→│ 2 │ 3 │      │ 0 │ 0 │
      ├───┤   └───┴───┘      └───┴───┘ ┌───┬───┐
      │ •→│→→→↑ ↑                      │ 0 │ 0 │
      ├───┤     ↑            ┌───┬───┐ └───┴───┘
      │ •→│→→→→→↑            │ 0 │ 0 │
      └───┘                  └───┴───┘

這當然意味着dp[1][0]dp[4][0]都指向同一個數組 position,即持有2值的 position。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM