Java,通过值,引用variables

在下面的例子中,我对理解Java的“传值”行为有一个问题:

public class Numbers { static int[] s_ccc = {7}; static int[] t_ccc = {7}; public static void calculate(int[] b, int[] c) { System.out.println("s_ccc[0] = " + s_ccc[0]); // 7 System.out.println("t_ccc[0] = " + t_ccc[0]); // 7 b[0] = b[0] + 9; System.out.println("\nb[0] = " + b[0]); // 16 c = b; System.out.println("c[0] = " + c[0] + "\n"); // 16 } public static void main(String[] args) { calculate(s_ccc, t_ccc); System.out.println("s_ccc[0] = " + s_ccc[0]); // 16 System.out.println("t_ccc[0] = " + t_ccc[0]); // 7 } } 

我知道,因为s_ccc是一个引用variables,所以当我给方法calculate(),并且对方法中的元素做一些更改时,甚至在离开方法之后,这些更改仍然保留。 我认为应该与t_ccc一样。 它又是一个引用variables,我给它的方法calculate(),并在方法中,我把参考t_ccc更改为s_ccc。 现在t_ccc应该是一个指向一个数组的引用variables,它有一个inttypes的元素,等于16,但是当方法calculate()剩下时,看起来t_ccc指向它的旧对象。 为什么发生这种情况? 这个变化是否也不应该呢? 毕竟它是一个参考variables。

问候

有一个关于Java如何在先前的问题中传递variables的扩展讨论“Java 是否被引用传递? ”。 Java确实通过值来传递对象引用。

在你的代码中,数组(是对象)的引用被传递到calculate() 。 这些引用是通过值传递的,这意味着对bc的值的任何更改都只能在方法中可见(它们实际上只是s_ccct_ccc的副本)。 这就是为什么main() t_ccc从不受影响的原因。

为了强化这个概念,一些程序员将方法参数声明为finalvariables:

 public static void calculate(final int[] b, final int[] c) 

现在,编译器甚至不允许你改变bc的值。 当然,这个缺点是你不能在你的方法中方便地操纵它们。

这是理解它的一个简单的方法。

Java总是传递参数的副本。 如果参数是基本types(例如整数),则被调用的方法获取原始值的副本。 如果参数是一个引用types,那么被调用的方法将获得该引用的副本( 而不是引用的副本)。

当你的main方法开始时,每个s_ccct_ccc指向一个不同的数组。 这就是情况,括号表示variables,方括号表示实际的数组结构:

 (s_ccc) ---> [7] (t_ccc) ---> [7] 

假设你的意思是calculate(s_ccc, t_ccc) ,那么在calculate方法的开始处:

 (s_ccc) ---> [7] <---(b) (t_ccc) ---> [7] <---(c) 

当地bc分别是全局variabless_ccct_ccc 拷贝

仍然在calculcate之后, b[0] = b[0] + 9已经完成:

 (s_ccc) ---> [16] <---(b) (t_ccc) ---> [7] <---(c) 

b引用的数组中的零(仅)位置已被修改。

calculate的赋值c = b产生这种情况:

 (s_ccc) ---> [16] <---(b) ^------(c) (t_ccc) ---> [7] 

本地引用variablesc现在包含与b相同的引用。 这对全局引用variablest_ccc没有影响,它仍然指向与之前相同的数组。

calculate退出时,其局部variables(在图的右侧)消失。 全局variables(左侧)没有用于calculate ,所以它们不受影响。 最后的情况是:

 (s_ccc) ---> [16] (t_ccc) ---> [7] 

c_ccct_ccc都没有改变。 每个仍然是指与之前calculate相同的数组。 调用calculate使用对该数组的复制引用 (在b )更改了由s_ccc引用的数组的内容

局部variablesc作为t_ccc一个拷贝开始,并在calculate内部被操作,但是既没有改变t_ccc本身,也没有改变它的参考数据。

该方法通过值接收variables。 这些值不能被改变(就方法的调用者而言),但是它们中包含的值可以(如果它是一个对象,或者在这种情况下是一个数组)。

所以当你改变数组中的值b [0]时,可以在方法外看到改变。 但是行

 c = b; 

会改变方法内部的c的值,但是这个改变不会在方法外部看到,因为c的值是通过值传递的。

calculate(s_ccc, s_ccc); 表示你实际上没有对t_ccc做任何事情。 但是,如果这行读取了calculate(s_ccc, t_ccc); 比效果保持不变。

这是因为你在这里给c赋一个新的值: c = b;
将新值分配给参考参数时,参考值将丢失。
这是改变参考variables和分配新值的区别。

calculate()b点在s_cccc点在t_ccc 。 如你所见,改变b[0]将会改变s_ccc

但是,分配

 c = b; 

只有在同一个对象b指向的点c ,即s_ccc 。 它不会将b点的内容复制到c点。 结果, t_ccc不变。 如果将以下行添加到calculate():的末尾calculate():

 c[0] = c[0] + 5; 

s_ccc[0]将是21。