【问题标题】:Why does this function in Java doesn't affect the result?为什么Java中的这个函数不影响结果?
【发布时间】:2013-05-19 01:25:28
【问题描述】:
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 行调用。

【问题讨论】:

  • 我不懂java,但也许list = reverse(list);?
  • 是的!这意味着我将不得不返回“newList”并将“void”更改为“int[]”,就像其他人提到的那样。谢谢

标签: java arrays function methods


【解决方案1】:
list = newList;

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

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

【讨论】:

    【解决方案2】:

    这是因为您通过值传递 list。即list = newList 行对调用者没有影响。在 Java 中,一切都是按值传递的。

    要做你想做的事,把你的功能改成

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

    在你的函数结束时。

    return newList;
    

    而不是

    list = newList;
    

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

    【讨论】:

    • 谢谢!现在这对我来说很有意义!
    【解决方案3】:

    你必须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;
       }
    }
    

    【讨论】:

    • 接受我的回答,如果你认为这是最有用的,请:)
    • 投票,让我解除限制:)
    【解决方案4】:

    问题在于 Java 参数传递是按值传递的。 reverse的最后一条语句是这样的:

        list = newList;
    

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

    要让reverse 方法正常工作:

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

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


    回应此评论:

    我正在阅读的书说数组是通过引用传递的,并且方法中的数组发生的任何事情都会影响 main 方法中的原始数组。或者我可能解释错了!

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

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

    “通过通过参考”

    ...和...

    “传递一个参考”

    ... 不是同一个意思。

    (事后看来,Gosling 等人将 Java 对象指针称为“引用”的决定是新 Java 程序员困惑的根源。OTOH,如果他们卡住了从 C 和 C++ 过渡的程序员,就会有另一种困惑使用旧术语“指针”。)

    【讨论】:

      【解决方案5】:

      问题是,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;
          }
      }
      

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 2022-11-18
        相关资源
        最近更新 更多