Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am starting to learn Java with the Java Trails tutorials offered by Oracle. I am in the section where it talks about passing arguments to methods The Java™ Tutorials: Passing Information to a Method or a Constructor.

It says that primitive types are passed by value, which makes sense to me. Right after that it says:

Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level.

Now this doesn't make sense to me. If an object is passed by value, then changing the fields of that object will change the fields of the copy inside the method, not the original one.

When testing with the program below:

class Point {
    int x;
    int y;

    public static void movePoint(Point p, int x, int y) {
        p.x+=x;
        p.y+=y;
    }
}
class App {
    public static void main(String argv[]) {
        Point p1;

        p1 = new Point();
        p1.x = 2;
        p1.y = 3;

        p1.movePoint(p1,2,2);

        System.out.println("x = " + p1.x +  " y = " + p1.y);
    }
}

It worked as if the object was being passed by reference (it prints out x = 4 y = 5 after all).

So what exactly did Oracle mean in the passage above? Also, can anyone summarize what's passed by value and what's passed by reference in Java?

share|improve this question
7  
This stackoverflow answer explains it well –  Mike L. Jan 24 '12 at 18:17
    
@Mile L., I forgot to search on SO before posting here. My bad, and thanks for the link anyway. –  daniels Jan 24 '12 at 18:19
    
You are right, @daniels: class instances (objects) are passed by reference in the literal sense: through passing the reference (pointer) by value. –  Ingo Feb 26 '13 at 10:37
    
This is a very common question, the definitive answer is, imho, Parameter passing in Java - by reference or by value –  Binary Worrier Apr 10 at 13:24
    
The implicit references are a characteristic of objects, not of parameter passing. For example object variables are implicitly "by-reference" too. Another way to explain it is that Java objects have reference semantics, whereas (most?/all?) other types have value semantics. –  Steve314 Jun 7 at 4:19

2 Answers 2

up vote 5 down vote accepted

Java is pass by value. Think of it like a pointer language like C, the value of the pointer (memory address) is being passed, so you have a reference to the same object. Primitives aren't stored internally the same way as Objects, so when you pass a primitive's value, it's the content, not a pointer.

share|improve this answer
1  
Gotcha, so when you pass the name of an object to a method you are actually passing a copy of it's memory address, right? –  daniels Jan 24 '12 at 18:18
    
Internally, yes. Though, if you were to pass an object (reference), say method(cat), the local variable holding the reference copied from cat could be changed to point to a new object, without changing the actual reference stored in cat. –  Sam DeHaan Jan 24 '12 at 18:21
    
Right. And I guess that's the reason we say that objects are passed by value (i.e., the value of their addresses). If they were passed by reference in the real sense of the word doing an attribution on the "cat" inside the method would also affect the original one. Correct? –  daniels Jan 24 '12 at 18:25
4  
@daniels: To avoid confusion, it is important to be very precise about terms. Java objects do not have names. Variables have names. A variable can store an object reference or a primitive value. –  kevin cline Jan 24 '12 at 18:42
3  
This specific kind of call-by-value-where-the-value-is-a-pointer is also called call-by-sharing or call-by-object-sharing. IOW: the caller and the callee have different pointers, but they may point to the same (mutable) object. Mutability is what is important here: for immutable objects call-by-value-where-the-value-is-passed-directly and call-by-sharing are actually indistinguishable. –  Jörg W Mittag Jan 25 '12 at 2:02

There is a test for whether a language is pass-by-reference: can you write a swap function, such that after swap(a,b), the caller finds that the values of a and b are reversed? You cannot do this in Java, not even for objects.

Note that you cannot achieve this goal by swapping the internals of the two objects - while the data may change, the identity of the objects has not, and this has consequences. For one thing, any other variable in the program that referenced either object would also see the change.

To see why you cannot write this swap, consider a simplified model of the language, in which the value of a reference variable is the address of the object it is currently bound to (garbage collection complicates this picture in a way not relevant here.) Before the call to swap, the caller's stack frame has a slot for a, containing the address of object A, and a slot for b containing the address of B. When swap is called, it receives the values of a and b, which are the addresses of A and B respectively. Therefore, it is decoupled from the caller: there is simply no way for it to find the addresses of the slots for a and b within the caller's stack frame, and therefore no way to set them so that the caller will see them swapped.

@supercat suggests an alternative way of looking at it: conceptually, a reference variable holds the unique ID of the object it references, something that is fixed for the life of the object, and it is this that gets copied to the function in a call. This view also makes it clear that the function has no way to find, let alone modify, the variable in the caller's stack frame.

Call-by-reference means exactly the opposite, by definition: the function accesses its arguments through the caller's variable bindings, so that changing one of its arguments' binding in the function necessarily changes it in the caller's stack frame. The term dates to a time when mainstream languages did not have objects or references as first-class entities, and when an argument was passed, either a copy of its value (in pass-by-value) or its address (in pass-by-reference) was pushed on to the stack so that the function could retrieve it. Passing an argument's address allows swap to work, but passing an address it contains does not.

Another way of looking at it: pass-by-reference does not mean pass the reference held in the argument variable, it means create, in the function, a local variable that references the argument variable.

Therefore, we can see that Java uses pass-by-value, not pass-by-reference.

See also Java is Pass-by-Value, Dammit! which also discusses argument-passing in Java RMI.

share|improve this answer
    
What do you think of my suggestion of saying that class-type variables hold "Object identifiers"? If local variable foo holds "Object #204" before boz(foo), then it will hold "Object #204" afterward. The actual contents of the variables can't be rendered in human-readable form, of course, but I think it's clear that whatever object is the 204th one created since program startup will always be the 204th object created since program startup as long as it exists. I much prefer object-id to address, because it is in fact entirely possible that... –  supercat Apr 14 at 23:09
    
...after local variables foo and bar are passed to a method, it might return with foo holding the address that bar used to have, and vice versa. IT would be unlikely, but if by chance the GC were to run a couple times and the last GC cycle happened to place foo where bar had been earlier and vice versa, such a swap could legitimately happen. The key point would be that if foo identified object #204 before the call, it would still do so afterward, even if the address of that object happened to change. –  supercat Apr 14 at 23:10
    
@ supercat You make a good point about reference variables as being holders of object identifiers (at least conceptually.) Having looked at several attempts to explain this issue, I chose to go with a discussion based on object addresses in a hypothetical, simplified Java-like language partly in order to make a straightforward comparison with how pass-by-reference might be implemented. I will see if I can incorporate your suggestion into the explanation. The TLDR is this: Java gives you no way to modify the caller's stack frame, while pass-by-reference would. –  mk7 Apr 16 at 4:53
    
@supercat I have incorporated your suggestion, with attribution - I hope I haven't misrepresented you. One reason I wrote my answer in its original form was to refute a claim that it couldn't be done this way without being exponentially more complicated than an alternative. –  mk7 Apr 24 at 12:45
    
Looks fine. One thing I like about using the terminology "Object #204" is that it attaches to each object a unique permanent identity which is easily understandable, even though Java does not. In Java, if object #204 were a Widget, and one were to create a new Widget (#451), copy all the fields from object #204 to #451, and replace every reference to object #204 everywhere in the universe with a reference to object #451 (abandoning the old one), the state of the universe would be indistinguishable from its state before the change if the object had no finalizer and identityHashCode... –  supercat Apr 24 at 15:45

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.