I have a problem with understanding the "pass-by-value" action of Java in the following example:
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 }}I know that because s_ccc is a reference variable, when I give it to the method calculate() and I make some changes to its elements in the method, the changes remain even after I leave the method. I think that the same should be with t_ccc. It is again a reference variable, I give it to the method calculate(), and in the method I change the referece to t_ccc to be that of s_ccc. Now t_ccc should be a reference variable pointing to an array, which has one element of type int equals to 16. But when the method calculate() is left, it seems that t_ccc points its old object. Why is this happening? Shouldn't the change remain for it, too? It is a reference variable after all.
Regards
- Did you mean calculate(s_ccc, t_ccc) instead of calculate(s_ccc, s_ccc) ?Luke Woodward– Luke Woodward2009-01-31 12:41:01 +00:00CommentedJan 31, 2009 at 12:41
- Yes, exactly! I do mean calculate(s_ccc, t_ccc). I am sorry.user42155– user421552009-01-31 12:51:27 +00:00CommentedJan 31, 2009 at 12:51
- @gemm: Could you amend your post please?Zach Scrivena– Zach Scrivena2009-01-31 13:07:07 +00:00CommentedJan 31, 2009 at 13:07
6 Answers6
There's an extended discussion of how Java passes variables at an earlier question "Is Java pass by reference?". Java really passes object referencesby value.
In your code, the references for the arrays (which are objects) are passed intocalculate(). These references are passed by value, which means that any changes to the values ofb andc are visible only within the method (they are really just a copy ofs_ccc andt_ccc). That's whyt_ccc inmain() was never affected.
To reinforce this concept, some programmers declare the method parameters asfinal variables:
public static void calculate(final int[] b, final int[] c)Now, the compiler won't even allow you to change the values ofb orc. Of course, the downside of this is that you can no longer manipulate them conveniently within your method.
Comments
Here's a simple way to understand it.
Java always passes copies of arguments. If the argument is a primitive type (e.g. an integer), then the called method gets a copy of the primitive value. If the argument is a reference type, then the called method gets a copy of the reference (not a copy of the thing referred to).
When yourmain method begins, each ofs_ccc andt_ccc refers to a distinct array.This is the situation, where parentheses indicate variables and square brackets indicate the actual array structures:
(s_ccc) ---> [7](t_ccc) ---> [7]Assuming that you meantcalculate(s_ccc, t_ccc), then at the beginning of thecalculate method:
(s_ccc) ---> [7] <---(b)(t_ccc) ---> [7] <---(c)Localsb andc arecopies of globalss_ccc andt_ccc respectively.
Still withincalculcate, afterb[0] = b[0] + 9 has completed:
(s_ccc) ---> [16] <---(b)(t_ccc) ---> [7] <---(c)The zero (only) positionin the array referred to byb has been modified.
The assignmentc = b withincalculate produces this situation:
(s_ccc) ---> [16] <---(b) ^------(c)(t_ccc) ---> [7]The local reference variablec, now contains the same reference asb. That has no effect on the global reference variablet_ccc, which still refers to the same array as before.
Whencalculate exits, its local variables (on the right-hand side of the diagrams) disappear. The global variables (on the left-hand side) were not used incalculate, so they are unaffected. The final situation is:
(s_ccc) ---> [16](t_ccc) ---> [7]Neitherc_ccc nort_ccc were changed; each still refers to the same array as beforecalculate. Callingcalculate changed thecontent of the array referenced bys_ccc, using acopied reference to that array (inb).
Local variablec started as acopy oft_ccc and was manipulated withincalculate, but that changed neithert_ccc itself nor it's referenced data.
Comments
The method receives variables by value. Those values can't be changed (as far as the caller of the method sees), but the values contained within them can (if it's an object, or as in this case, an array).
So when you change the value b[0] inside the array, the change can be seen outside the method. However the line
c = b;will change the value of c inside the method, but that change will not be seen outside the method, since the value of c was passed by value.
Comments
The linecalculate(s_ccc, s_ccc); indicates you're not actually doing anything to t_ccc.However, should this line have readcalculate(s_ccc, t_ccc); than the effect remains the same.
This is due to the fact that you're assigning a new value to c here:c = b;
When assigning a new value to a reference argument the reference is lost.
This is the difference between altering a by reference variable and assigning a new value.
Comments
On entry tocalculate(),b points ats_ccc andc points att_ccc. Alteringb[0] will therefore changes_ccc, as you've seen.
However, the assignment
c = b;only pointsc at the same objectb is pointing at, namelys_ccc. It does not copy the contents of whatb points to to whatc points to. As a result,t_ccc is unchanged. If you added the following line to the end ofcalculate():
c[0] = c[0] + 5;s_ccc[0] would be 21.
Comments
Passing Arrays to Methods in JavaIn Java, when an array (or any object) is passed to a method, what you're actually passing is the reference to that array. However, it's important to understand that Java is strictly "pass-by-value." This means the method gets a copy of the reference, not the actual reference itself.
Modifying Array ElementsIf you modify the elements of the array within the method (e.g., b[0] = b[0] + 9;), you are altering the contents of the array that the reference points to. These modifications are reflected outside the method because both the original reference and the method's copy of the reference point to the same array.
Changing the Reference ItselfOn the other hand, if you change the reference itself within the method (e.g., c = b;), you are only modifying the local copy of the reference, not the original reference that was passed in. As a result, this change does not affect the original reference outside the method.
Comments
Explore related questions
See similar questions with these tags.