更改Java中方法中传递的参数的值?

时间:2015-01-05 08:06:44

标签: java android

在我了解详细信息之前,我想清楚地表明 I do understand that Java is Pass-by-Value and not Pass-by-Reference ,但是因为我看过某些功能,所以我很困惑去做。我想知道他们是怎么做的。

我想要发生的事情:

public void yo() {
    int a = 1;
    String b = "hello";
    Boolean c = false;

    doSomething(a,b,c);

    // a,b,c should have new values
}

public void doSomething(int x, String y, Boolean z) {
    // Do Something
}

我见过的功能是这样做的:

// Works in Android Development

int[] location = new int[2];
view.getLocationInWindow(location);

// `location` has a new value now
// Same happens when you run getLocationOnScreen(arg)

这是如何运作的?

5 个答案:

答案 0 :(得分:7)

首先:你是绝对正确的,Java纯粹是按值传递。

要记住的关键是当我们有一个像location这样的变量引用一个数组或对象时,该变量实际上包含数组或对象,它包含引用到内存中其他位置的数组或对象。这是数组/对象和基元之间的最大区别。请考虑以下代码:

int primitive = 5;
int[] ref = new int[2];

这让我们记忆犹新:

+-----------+
| primitive |
+-----------+
| 5         |
+-----------+

+-----------+
| ref       |
+-----------+      +--------+
| reference |----->| int[2] |
+-----------+      +--------+
                   | 0      |
                   | 0      |
                   +--------+

注意区别。那么上面的“参考”是什么?它是一个值,如123456789,VM用于在内存中定位数组。我们不知道价值,我们不关心它。我们关心的只是VM知道如何解释它。

因此,您引用的代码可以修改数组,因为传递给函数的值是数组的引用的副本,而不是数组的副本。使用该引用来修改数组会修改该数组的一个副本,因此无论您使用哪个副本来查看,都可以看到这些修改。

这一行之后:

int[] location = new int[2];

......我们在记忆中有这个:

+-----------+
| location  |
+-----------+       +--------+
| reference |------>| int[2] |
+-----------+       +--------+
                    | 0      |
                    | 0      |
                    +--------+

然后,当你这样做时:

view.getLocationInWindow(location);

getLocationInWindow内,它会收到引用的副本(因为Java是按值传递),所以说getLocationInWindow的参数名是{{1在电话会议中我们有这个:

+-----------+
| location  |
+-----------+       +--------+
| reference |---+-->| int[2] |
+-----------+   |   +--------+
                |   | 0      |
                |   | 0      |
+-----------+   |   +--------+
| foo       |   |
+-----------+   |
| reference |---+
+-----------+

通过引用的任一副本访问数组,访问相同的数组。 (同样,对象引用也是如此。)

答案 1 :(得分:2)

public class Main {

    public void changeArrayContents(int[] array) {
         array[0]++;
    }

    public void makeArrayNull(int[] array) {
         array = null;
    }

    public static void main(String[] args) {
         int[] array = new int[5];
         array[0] = 3;
         System.out.println(array[0]); // prints 3 (duh)
         changeArrayContents(array);
         System.out.println(array[0]); // prints 4
         makeArrayNull(array);
         System.out.println(array[0]); // prints 4 (does not throw NullPointerException)
    }
}

在此示例代码中,changeArrayContents 不会更改其参数。 更改变量值的唯一方法是通过赋值 - 包括复合赋值(+=*=等)以及带有++--的缩写表单。< / p>

“但那里有一个++!”你说。是的,但请注意它是array[0]++,而不是array++。要更改的内容是array[0],而不是array

当您编写array[0](或object.something),然后时,JVM会查找实际的数组 - 它不存储在变量中 - 并访问第一个元素

调用changeArrayContents(array)会复制变量array(就像arrayintboolean一样)但它确实如此复制它引用的实际数组。现在有两个对同一个数组的引用,我们可以通过任何一个更改它,并通过另一个看到更改。

调用makeArrayNull(array)也会生成变量array的副本,而不会复制数组本身。这里的区别是array = null仅影响参数array。 <{1}}(也称为main)中的局部变量不受影响。

答案 2 :(得分:1)

传递值(即基本类型,例如int,double等)与传递对象的引用之间存在根本区别。如果更改引用指向的对象的属性,则将更新原始对象。对象不按值传递。您传递对该对象的引用。

这就是为什么它在你传递对数组的引用时起作用,而不是在传递一个整数时(即。)

答案 3 :(得分:1)

int[] location = new int[2];
view.getLocationInWindow(location);

// `location` has a new value now

我不确定你的意思是'位置价值'。由于变量“location”是一个数组,因此它的值是指向数组值的引用。 'location'的值没有改变,但是数组的值发生了变化。

location->location[1],location[2]

如上所述,更改的是位置[1],位置[2]的值,而不是位置。

答案 4 :(得分:0)

当您将数组传递给任何方法时,它的引用将传递给方法,这意味着如果您更改引用所指向的数组内容中的任何内容,它将反映从方法返回时的更改。 但是,如果您将该引用指向其他某个数组,并从该方法返回,则不会更改现有数组(或内容)