1
class Test {
    public static void main(String[] args) {
        int[] list = {1, 2, 3, 4, 5};
        reverse(list);
        for (int i = 0; i < list.length; i++) {
            System.out.print(list[i] + " ");
        }
   }

   public static void reverse(int[] list) {
       int[] newList = new int[list.length];

       for (int i = 0; i < list.length; i++) {
           newList[i] = list[list.length - 1 - i];
       }

       list = newList;
   }
}

当我运行这个程序时,答案是 1 2 3 4 5。这个“反向”方法在第 4 行被调用。

4

5 回答 5

4

您必须return使用新列表,而不是修改参数引用,因为它只是方法范围的。

class Test {
    public static void main(String[] args) {
        int[] list = {1, 2, 3, 4, 5};
        list = reverse(list);
        for (int i = 0; i < list.length; i++) {
            System.out.print(list[i] + " ");
        }
   }

   public static int[] reverse(int[] list) {
       int[] newList = new int[list.length];

       for (int i = 0; i < list.length; i++) {
           newList[i] = list[list.length - 1 - i];
       }

       return newList;
   }
}
于 2013-05-23T15:35:20.983 回答
3
list = newList;

您刚刚更改了本地参数以引用一个新的数组实例。

这不会影响调用者的变量,它仍然引用您传递的原始数组实例。

于 2013-05-23T15:34:30.757 回答
2

这是因为你是按价值传递list的。即线路list = newList对呼叫者没有影响。在 Java 中,一切都是按值传递的。

做你想做的事,改变你的功能

public static int[] reverse(int[] list)

并在您的功能结束时。

return newList;

代替

list = newList;

更正式地说,对数组的引用是按值传递的。当您重新分配 list = newList 时,您正在将参考点指向不同的数组。但是调用者中的引用没有改变,因此指向原始数组。

于 2013-05-23T15:34:33.730 回答
1

问题是 Java 参数传递是按值传递的。最后的声明reverse是这样的:

    list = newList;

不幸的是,由于list是一个参数(并且是按值传递的),这个赋值不会影响方法list中的值main

要使该reverse方法正常工作:

  • 更改它以返回反向列表(并将结果分配给listin main),或
  • 更改它以list从 的相应单元格中分配 的单元格newList

(顺便说一句,如果您要list就地更新,则无需单独的newList数组即可。)


针对此评论:

我正在阅读的书说,数组是通过引用传递的,无论方法中的数组发生什么,都会影响 main 方法中的原始数组。或者也许我解释错了!

要么这本书是错的,要么你误解了它。(我怀疑可能是后者。)Java 中的所有类型(即所有类型)都按值传递,并按值返回。

稍微令人困惑的是,在引用类型的情况下,传递或返回的值是对象的引用。这为误解术语(或一本书有点草率)留下了空间,但是......

“通过引用传递”

... 和 ...

“通过参考

......不是同一个意思。

(事后看来,Gosling 等人将 Java 对象指针称为“引用”的决定是新 Java 程序员困惑的根源。OTOH,如果程序员坚持使用旧的 C 和 C++,他们将会有不同的困惑术语“指针”。)

于 2013-05-23T15:37:47.817 回答
1

问题是,Java 按值传递对数组的引用。也就是说,reverse正在修改的引用不是调用者的版本,而是仅为此调用制作的副本。调用者将永远不会看到重新分配。

最终结果是您可以随心所欲地修改数组,但不能以调用者看到的方式将其替换为不同的数组。在 Java 中没有办法做到这一点,除非创建一个包装类。

完成后,您可以通过将新数组复制到旧数组中来获得所需的结果。即:而不是

list = newList;

System.arraycopy(newList, 0, list, 0, list.length);

如果您确定始终希望它修改原始数组,您也可以将其反转:

public static void reverse(int[] list) {
    for (int i = 0, j = list.length - 1; i < j; ++i, --j) {
         int temp = list[i];
         list[i] = list[j];
         list[j] = temp;
    }
}

这避免了创建一个你将要扔掉的对象。

但是,如果您预见到只需要数组的反向副本,而不是总是修改给定的副本,则最好返回新数组并让调用者决定如何处理它。

于 2013-05-23T23:39:37.070 回答