首页 > 解决方案 > 更改添加到堆栈的变量值而不更改堆栈?

问题描述

我有一堆数组。我还有一个数组,我将其推入堆栈、修改并再次推入。每当我更改数组的值时,堆栈中的所有变量都会以相同的方式进行修改。例如:

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});,但这会导致错误。我也不能每次都声明一个新数组,因为整个事情都是在循环中发生的。

标签: javaarraysstack

解决方案


您的代码无法编译。让我们忽略不编译和解释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-ese:走到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创造新的宝藏。我们在这里要两件宝物:一件是{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 放入其中。


推荐阅读