简体   繁体   English

修改本地var之外的变化?

[英]Modifying local vars changes outside vars?

I'm trying to understand how the below implementation of QuickSort works in Java. 我试图了解QuickSort的以下实现在Java中的工作方式。 I've got most of it, but I'm pretty confused how it does anything at all. 我已经掌握了大部分,但是我很困惑它怎么做。 When you pass in a variable to a function and modify it, it normally doesn't modify the original variable that was passed in. So why does this implementation of quicksort with no return type modify the array passed in? 当您将变量传递给函数并对其进行修改时,它通常不会修改传递的原始变量。那么为什么没有返回类型的quicksort实现会修改传递的数组呢?

public static void quickSort(int[] arr, int low, int high) {
    if (arr == null || arr.length == 0)
        return;

    if (low >= high)
        return;

    int middle = low + (high - low) / 2;
    int pivot = arr[middle];

    // make left < pivot and right > pivot
    int i = low, j = high;
    while (i <= j) {
        while (arr[i] <pivot) {
            i++;
        }

        while (arr[j] > pivot) {
            j--;
        }

        if (i <= j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++;
            j--;
        }
    }

    if (low < j)
        quickSort(arr, low, j);

    if (high > i)
        quickSort(arr, i, high);
}

because arrays are treated as Object´s, and in this case they pass the value of the reference to the method, which causes this implementation to work on the array that was passed to this method. 因为数组被视为对象的数组,在这种情况下,它们将引用的值传递给该方法,这导致该实现在传递给此方法的数组上起作用。

It´s the same as if you would do 就像你会做的一样

public void test(ObjectA obj) {
    obj.setVal(1);
}

In this case you would work on the passed ObjectA and would also invoke the method setVal on this instance. 在这种情况下,你会工作在传递ObjectA也将调用方法setVal在这种情况下。 In this case the method invoking inside the method test would also reflect in changes inside the passed instance of this specific objects (because it´s the same instance). 在这种情况下,在方法test调用的方法还将反映在此特定对象的传递实例内部的更改(因为它是同一实例)。

The same happens for arrays 数组也是如此

public static void main(String args[]) {
   int[] arr = {1,2,3};
   test(arr);
   System.out.println(arr[0]); // This would print 13 now.
}

public static void test(int[] arr) {
   arr[0] = 13;
}

For further reference you could go through this question 为了进一步参考,您可以解决这个问题

Your int[] arr is a reference to an array. 您的int[] arr是对数组的引用。 This reference is a copy of the reference passed to it, and that reference cannot be changed. 该引用是传递给它的引用的副本,该引用不能更改。 However, the array it references, is not copied and when you modify it, these changes are visible to the caller. 但是,它所引用的数组不会被复制,并且在您对其进行修改时,这些更改对于调用者是可见的。

Everything in Java is passed by value. Java中的所有内容都是按值传递的。 If we are talking about non-primitives - Object variables as well as arrays, the VALUE of the variable is a LINK to the object. 如果我们谈论的是非原始对象-对象变量以及数组,则变量的VALUE是指向对象的LINK。 We can't re-assign the link, but we can change internals of the object. 我们无法重新分配链接,但是我们可以更改对象的内部。

The thing is that when we pass primitives - they are kept in Stack of the function and their change won't affect value of the variable in method call. 事实是,当我们传递原语时,它们被保存在函数的Stack中,并且它们的更改不会影响方法调用中变量的值。 But objects are in Heap and they are shared. 但是对象在堆中并且被共享。 So we can change it's internals from any place of the call stack. 因此,我们可以从调用堆栈的任何位置更改其内部。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM