我有一堆数组。我还有一个数组,我将它推入堆栈,修改并再次推入。每当我更改数组的值时,堆栈中的所有变量都会以相同的方式进行修改。例如:
int[] array = {1, 1};
Stack<int[]> stack = new Stack<int[]>();
stack.push(array);
array = {1, 3};
stack.push(array);
堆栈应该是{{1, 1}, {1, 3}}
,而是{{1, 3}, {1, 3}}
。我试过 stack.push({1, 3});
但这会导致错误。我也不能每次都声明一个新数组,因为这整件事都是在循环中发生的。
答案 0 :(得分:2)
您的代码无法编译。不编译解释java的部分先不说。
<块引用>我也不能每次都声明一个新数组,因为整个过程都在循环中发生。
诺诺。你可以。 int[]
是一种对象类型(与原始类型相反)。这意味着变量实际上代表的是一张藏宝图,而不是宝藏。所以,让我们分解一下:
int[] array = {1, 1};
这只是语法糖:
int[] array = new int[] {1, 1};
这只是语法糖:
int[] array = new int[2];
array[0] = 1;
array[1] = 1;
此外,new int[2]
命令创建了新的宝藏并将其埋在沙子中,int[] array
部分创建了一个新的藏宝图,中间的 =
写了一个漂亮的 X-在您的地图上标记该地点。 []
和 .
是 Java 语言,用于:走到 X 并向下挖掘。 =
是 java-ese 的意思:拿一块橡皮擦把那个 X 擦掉,然后把它放在别的地方。
此外,在 Java 中,每当您将内容传递给方法时,它总是副本(但是,map 的副本,而不是 treasure 的副本)。
这种思考方式正是 Java 内存模型的工作方式,永远不会误导您。因此:
int[] array = {1, 1};
// 1 treasure chest made.
// 1 treasure map made. The map is called `array`.
// X marked on the map.
stack.push(array);
// Take your `stack` map, walk to the X. Dig down.
// Open the chest you find here, and yell into it: "push".
// Make a copy of your `array` map, and hand it over.
array = {1, 3};
// This isn't legal java.
array[1] = 3;
// This takes your array map, follows the X,
// digs, tosses out the second element you find
// in the box, and then puts a 3 in there instead.
当然堆栈看到的是相同的 3:只有一个宝藏,而且你们都有一张地图。
让我们修复它。请记住,=
会消灭 X,而 new
会创造新的宝藏。我们在这里想要 2 个宝藏:一个是 {1, 1}
,另一个是 {1, 3}
。因此,涉及到 new
,而 =
也很有用。让我们使用它们:
int[] array = {1, 1};
stack.push(array);
array = new int[] {1, 3};
// The above is the syntax for making a new int array.
stack.push(array);
System.out.println(stack);
成功!现在它可以工作了。
原因 int[] x = {1, 3};
是合法的,但 x = {1, 1};
不是,是语言的一个怪癖。它在语言规范中。 int[] x = ...
使用初始化器声明一个新变量,而 x = ...
是一个赋值表达式。
Java 需要知道您要创建的数组的类型。写int x = { ... }
时很明显。当您编写 x = { ... }
时,这可能不太明显,这大概是为什么规范不允许速记。请注意,写 int[] x = new int[] {1, 3};
也完全没问题; int x[] = {1, 3};
只是方便的简写。
// 这需要你的数组映射,跟随 X, // 挖掘,扔掉你找到的第二个元素 // 在盒子里,然后在那里放一个 3。
答案 1 :(得分:2)
我猜你的语法只是对循环中代码的简化。
由于您的要求是使用相同的数组实例,而无需创建更多数组,您需要的是在每次迭代时推送此数组的浅拷贝。基元的浅克隆不会受到对同一对象的进一步修改的影响,因此将复制正确的值,而不会因您在后续迭代中所做的更新而改变。
就这样:
int[] array = {1, 1};
Stack<int[]> stack = new Stack<int[]>();
stack.push(array.clone());
//array = {1,3}; ---> in order to mimic this, I manually alter array's values
array[0]=1;
array[1]=3;
stack.push(array.clone());
您的堆栈现在将保存正确的值
stack [0] --> {1,1}
[1] --> {1,3}
或者,每次您都可以将一个新数组分配给 array
,例如
import java.util.Arrays;
import java.util.Stack;
public class Main {
public static void main(String args[]) {
int[] array = { 1, 1 };
Stack<int[]> stack = new Stack<int[]>();
stack.push(array);
array = new int[] { 1, 3 };
stack.push(array);
stack.forEach(e -> System.out.println(Arrays.toString(e)));
}
}
输出:
[1, 1]
[1, 3]