在我了解详细信息之前,我想清楚地表明 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)
这是如何运作的?
答案 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
(就像array
是int
或boolean
一样)但它确实如此不复制它引用的实际数组。现在有两个对同一个数组的引用,我们可以通过任何一个更改它,并通过另一个看到更改。
调用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)
当您将数组传递给任何方法时,它的引用将传递给方法,这意味着如果您更改引用所指向的数组内容中的任何内容,它将反映从方法返回时的更改。 但是,如果您将该引用指向其他某个数组,并从该方法返回,则不会更改现有数组(或内容)