8

I read this comment here: Passing a String by Reference in Java?

Yes, it's a misconception. It's a huge, widespread misconception. It leads to an interview question I hate: ("how does Java pass arguments"). I hate it because roughly half of the interviewers actually seem to want the wrong answer ("primitives by value, objects by reference"). The right answer takes longer to give, and seems to confuse some of them. And they won't be convinced: I swear I flunked a tech screen because the CSMajor-type screener had heard the misconception in college and believed it as gospel. Feh. – CPerkins Aug 13 '09 at 14:34

Can someone please explain, in terms that a new programmer can grasp, what is the difference between saying:

"In Java primitives are passed by value and objects are passed by reference."

and:

"In Java nothing is passed by reference and references are passed by value."?

Are both of these statements true in some sense? I don't want to invite a rant parade, but this sounds like a really important concept, and one I still do not completely understand.

Community
  • 1
  • 1
Steve the Maker
  • 611
  • 6
  • 11
  • 2
    Possible duplicate: http://stackoverflow.com/questions/40480/is-java-pass-by-reference – assylias Feb 27 '12 at 16:05
  • See http://www.javaranch.com/campfire/StoryPassBy.jsp & http://www.yoda.arachsys.com/java/passing.html – Zaki Feb 27 '12 at 16:06
  • 1
    I believe [this](http://stackoverflow.com/a/795186/1101070) might be the answer you're looking for. – Marvin Pinto Feb 27 '12 at 16:06
  • 1
    Java passes by value, PERIOD. For objects, the value passed is the reference to the object. – Zaki Feb 27 '12 at 16:08
  • 2
    IMO, knowing the terminology isn't that helpful. Knowing what actually happens is. I saw a handy question a few years ago involving `StringBuffer`s which really determines whether a programmer knows the rules without having to know the terminology. Wish I took a reference to that (or a copy, I'd certainly have to copy the reference). – Tom Hawtin - tackline Feb 27 '12 at 16:09
  • 2
    Voting to close. Exact duplicate of http://stackoverflow.com/questions/40480/is-java-pass-by-reference – dty Feb 27 '12 at 16:13
  • 2
    I understand the body of the questions are similar, but I'd also like to know why all the textbooks make the top statement and all of the programmers with chops make the bottom statement... if it's just a context thing and they're both right, or if the books are just flat out wrong. – Steve the Maker Feb 27 '12 at 16:18
  • 1
    Hey Check More about By Ref By Val http://www.cse.yorku.ca/~mack/1011/PassByReference.PDF – Sanjay Goswami Feb 27 '12 at 16:08
  • 2
    @StevetheMaker, they are at least right in that objects are not passed by taking a copy of the object. I'm sure most authors would elaborate on the *why*. They can correcly use any term, as long as they define it properly. – Johan Sjöberg Feb 27 '12 at 16:22
  • It's also a really intimidating comment for a new programmer. I don't want to fail interviews because of people who don't really understand their languages under the hood... Is that sort of thing common in the industry? – Steve the Maker Feb 27 '12 at 22:12

4 Answers4

12

I believe the misconception lies in the fact that a variable can not contain an object to begin with. If you grasp that, then obviously variables can only contain references to objects (or primitive values). The step from there to realizing that references are passed by value (just as primitive values) is quite small.

There is a really easy test you can do to figure out if a language supports pass by reference. Ask yourself if you can write a swap function in the language, i.e. something that works like

x == A, y == B

swap(x, y);

x == B, y == A

As a Java programmer you realize quickly that you can't implement this in Java, thus you (correctly) draw the conclusion that Java does not have pass by reference.

Returning to your sentences:

  • In Java primitives are passed by value and objects are passed by reference.

This is false. I would argue that you can only pass something that is contained in a variable, and as I stated above, a variable can't contain an object, thus you can't pass an object at all in Java.

  • In Java nothing is passed by reference and references are passed by value.

This is true.

aioobe
  • 413,195
  • 112
  • 811
  • 826
7

Things like this are always easier when drawn. Consider the following two variables, one being a primitive-type and one being a reference-type:

    int i    = 5;
    String s = "test";

somewhere in memory there is an entry for i that looks like this:

  i
-----
| 5 |
-----

similarly there is also an entry for s in memory but it refers to a location on the heap since s is a reference-type variable and objects are stored on the heap:

                            ----------- 
 s                 |------->|  "test" |
-----              |        |---------|
| --|--------------|        |         |
-----                       |         |
                            |         |
                            |---------|

So the value of s is the reference to that String object that is sitting on the heap, so if s were passed to a method:

printString(s);

public void printString(String arg)
{
   System.out.println(arg);
}

The value that actually gets copied into the arg parameter is that reference to s on the heap:

                            ----------- 
 s                 |------->|  "test" |<-----|
-----              |        |---------|      |
| --|--------------|        |         |      |
-----                       |         |      |
                            |         |      |
                            |---------|      |
 arg                                         |
-----                                        |
| --|----------------------------------------- 
-----

Hope this helps.

Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170
6

Good question. Consider the following sample

void foo(Object obj) {
  obj = new Foo(); 
}
Object o = new Bar();
foo(o);
// is o Foo or Bar?
  • If pass by-reference the o reference could have changed after calling foo
  • If pass by-reference-by-value the reference o is unchanged after calling foo
Johan Sjöberg
  • 47,929
  • 21
  • 130
  • 148
2

Both statements are mutually exclusive, and the first statement is false. In Java everything is passed by value, even references to objects. The confusion stems from the fact that when an object is passed by value, it's a copy of its reference what gets passed, and if the object is mutable and gets modified inside a method the changes will be visible from the outside in the point where it was called.

Let me explain with a couple of examples. In this case x is a primitive type passed by value:

void m(int x) {
    x = 10;
}
// in some other place, the above method gets called
x = 5;
m(x);
// in here, x's value is still 5

In this case, x is an object type and a copy of its reference is passed by value:

void m(ArrayList<Integer> x) {
    x.add(10);
}
// in some other place, the above method gets called
ArrayList<Integer> x = new ArrayList<Integer>();
x.add(5);
m(x);
// in here, x contains [5, 10]
Óscar López
  • 232,561
  • 37
  • 312
  • 386