【问题标题】:Array seems to be getting passed by reference in Java, how is this possible? [duplicate]数组似乎在 Java 中通过引用传递,这怎么可能? [复制]
【发布时间】:2011-06-21 01:11:07
【问题描述】:

如果需要,我可以发布更多代码,但在此之前,我只想问一个关于以下方法的一般问题,其中传递一个数组,然后设置为另一个数组,但由于某种原因原始数组,传入的那个也正在改变,这怎么可能/我该怎么办? 谢谢

tempBoard 是一个与 currentState 大小相同的数组,temp[k] 包含在 movePiece 中所做的更改,当前状态在方法中声明并且不是全局变量

private int[][] MiniMaxBaseCase(int[][] currentState, int currentColor)
{
    tempBoard = movePiece(currentState,temp[k]);
}

private int[][] movePiece(int[][] currentState, int[] move)
{
    if(move[0] == -1)
        return currentState;

    //if the piece is just moving
    if(move[4] == -1)
    {
        currentState[move[2]][move[3]] = currentState[move[0]][move[1]];
        currentState[move[0]][move[1]] = 0;
        return currentState;
    }

    //if the piece is jumping another
    if(move[4] != -1)
    {   
        currentState[move[4]][move[5]] = currentState[move[0]][move[1]];
        currentState[move[2]][move[3]] = 0;
        currentState[move[0]][move[1]] = 0;
        return currentState;
    }

    return currentState;
}

【问题讨论】:

  • 数组是对象。对象是引用类型。这并不奇怪。
  • 根据到目前为止我所看到的所有地方,在 java 中不可能通过引用传递,但是,可以通过值传递对象引用。这些有什么区别。
  • Jon 的网站对我来说似乎已关闭,但这里是缓存链接:webcache.googleusercontent.com/search?q=cache:http://…

标签: java arrays pass-by-reference


【解决方案1】:

在 Java 中:

  • 方法参数确实是按值传递,但是
  • Java 中的所有对象和数组变量都是引用变量

引用变量按值传递的净效果是指向的对象或数组引用变量是通过引用传递

您的数组实际上是通过引用传递的——它是同一个数组。

具体来说,MiniMaxBaseCase 中的currentState 是对数组的引用——它的值是数组的内存位置。 MiniMaxBaseCase 中的currentState 按值传递给movePiece,因此如果将MiniMaxBaseCase(内存位置)中的currentState 的值复制到movePiece 中的参数currentState 中 - 引用是按值传递的.但是现在movePiece 中的currentState 指向与MiniMaxBaseCase 中的currentState 相同的内存位置。所以现在两个变量都指向同一个数组,即最终效果是数组实际上是通过引用传递的。


编辑:复制多维数组

有些人一直建议直接使用System.arraycopy()Array.copyOf(),而不需要遍历第一个维度/索引。这行不通。

改用这个:

public static int[][] copyOf(int[][] original) {
    int[][] copy = new int[original.length][];
    for (int i = 0; i < original.length; i++) {
        copy[i] = Arrays.copyOf(original[i]);
    }
    return copy;
}

直接复制不起作用的原因是因为在 Java 中,二维数组实际上是指向(分散的)一维数组集合的指针/引用数组,即,int[][] 是一个数组指向一堆(分散的)int[] 的指针。简单地在二维数组上执行System.arraycopy()Arrays.copyOf() 将简单地将指针复制到分散的int[] 数组,即这个浅拷贝最终会共享底层数组集。您必须按照上面的代码进行深拷贝。

一些参考资料:

How do I do a deep copy of a 2d array in Java?

是的,您应该遍历 2D 布尔数组以进行深度复制。

http://www.cs.dartmouth.edu/~spl/Academic/Java/JFAQs.html
如何复制多维数组?

... 然而,复制二维数组更成问题,因为多维数组表示为数组的数组。这是克隆阵列时的问题。 System.arraycopy() 将为您提供对嵌入式数组的引用的副本。 ...

【讨论】:

  • 那么我该怎么做才能不改变原来的样子?
  • 对对象引用(您不想触摸其对象)执行相同的操作:首先克隆该对象。
  • @Jeremy - 我相信System.arraycopy() 会在我们想要深拷贝的地方做浅拷贝。
  • @Bert F - 很好,我想我从来不需要复制二维数组。好东西。
【解决方案2】:

在 Java 中没有传递引用之类的东西。你似乎知道这一点,并想知道为什么它仍然感觉这就是这里发生的事情......

问题是,数组是对象。对象实际上是指针。所以你得到了指向数组的指针的副本,但它仍然是它指向的数组。

如果您想在对数组进行任何更改之前创建数组的副本,请使用 System.arraycopy()。

【讨论】:

  • 您可能需要指出在二维数组上使用 System.arraycopy() 时要小心 - 天真地使用,您最终会得到一个不是独立副本的浅拷贝原始数组。
【解决方案3】:

花点时间好好阅读这篇文章。

http://www.cs.toronto.edu/~dianeh/tutorials/params/

跳到“传递数组”

数组是引用。这意味着当我们将数组作为参数传递时,我们传递的是它的句柄或引用。所以,我们可以在方法内部改变数组的内容。

这是来自“148:计算机科学导论”课程,它应该适合 Java 语言的前 2 课。

要将数组的副本传递给函数,在 Java 1.6 中,您可以使用 Array.copyOf,例如

tempBoard = movePiece(Arrays.copyOf(currentState, currentState.length), temp[k]);

注意: Array.copyOf 仅适用于基元的一维数组。用于其他任何东西,它为您提供了一个独立的数组,所有元素都相同并指向原始数组,无论是对象还是嵌套数组。

【讨论】:

  • 我相信这个copyOf 会做一个二维数组的浅拷贝,并且不会创建一个完全独立于原始数组的数组的真正深拷贝.
  • @BertF:引用类型的数组封装了其中包含的对象的身份,以及它们状态的不可变方面,但不封装其状态的任何可变方面。一个数组包含对对象的引用,这些对象的可变状态被初始化为源数组中相应成员的状态,这并不是源数组的真正副本,而是完全不同的东西。
猜你喜欢
  • 2022-06-16
  • 2020-04-12
  • 1970-01-01
  • 2013-06-30
  • 2016-08-19
  • 2021-02-09
  • 2015-08-22
  • 2021-10-14
  • 2010-10-10
相关资源
最近更新 更多