jQuery in Action, 2nd edition





java hosting


 

Pass-by-Value Please (Cup Size continued)

If you haven't read the Cup Size story, this one won't make sense. Or it will make sense, but you'll think its really stupid. Or you won't think it's stupid but you'll find yourself... never mind, just go read it now and then come back.

I really care about my cups.

I don't want just anybody putting something in my cups. If I have something in a cup, I just want it to stay that way until I decide to change it! So back off!

So if a Java variable is a cup, with a value in it, what does it mean to "pass" a variable to a method? And are primitives and references treated the same way?

We'll get there, but first let's start with simple assignment.

What does it mean to say:

1) int x = 3;

2) int y = x;

 

In line 1, a cup called x, of size int, is created and given the value 3.

In line 2, a cup called y, of size int, is created and given the value... 3.

The x variable is not affected!

Java COPIES the value of x (which is 3) and puts that COPY into y.

This is PASS-BY-VALUE. Which you can think of as PASS-BY-COPY. The value is copied, and that's what gets shoved into the new cup. You don't stuff one cup into another one.

Saying int y = x does NOT mean "put the x cup into y". It means "copy the value inside x and put that copy into y".

If I later change y:

y = 34;

Is x affected? Of course not. The x cup is still sitting there, all happy.

If I later change x:

x = 90;

Is y affected? Nope. They are disconnected from one another once the assignment was made (the COPY was made).

SO... what about Reference Variables (remote controls)? How does THAT work?

Not so tricky, in fact the rule is the same.

References do the same thing. You get a copy of the reference.

So if I say:

Cat A = new Cat();

Cat B = A;

 

The remote control in A is copied. Not the object it refers to.
You've still got just one Cat object.
But now you have two different references (remote controls) controlling the same Cat object.

 

NOW let's look at passing values to methods

Java is pass-by-value.

Always.

That means "copy the value, and pass the copy."

For primitives, it's easy:

int x = 5;
doStuff(x);
// pass a COPY of x (the value 5) to the doStuff method

The doStuff method looks like this:

void doStuff(int y) {

   // use y in some way
}

A copy of the value in x, which is 5, is passed into the doStuff() method.

The doStuff() method has its own new cup, called y, waiting.
The y cup is a new, different cup. With a copy of what was in x at the time it was passed. From this point on, y and x have no affect on each other. If you change y, you don't touch x.

 

void doStuff(int y) {

   y = 27; // this does NOT affect x
}

And vice-versa. If you change x, you don't change y.

The only part x had in this whole business was to simply copy its value and send that copy into the doStuff() method.

 

How does pass-by-value work with references?

Way too many people say "Java passes primitive by value and objects by reference". This is not the way it should be stated. Java passes everything by value. With primitives, you get a copy of the contents. With references you get a copy of the contents.

But what is the contents of a reference?

The remote control. The means to control / access the object.

When you pass an object reference into a method, you are passing a COPY of the REFERENCE. A clone of the remote control. The object is still sitting out there, waiting for someone to use a remote.The object doesn't care how many remotes are "programmed" to control it. Only the garbage collector cares (and you, the programmer).

So when you say:

Cat A = new Cat();
doStuff(A);

void doStuff(Cat B) {

   // use B in some way
}

 

There is still just ONE Cat object. But now TWO remote controls (references) can access that same Cat object.

So now, anything that B does to the Cat, will affect the Cat that A refers to, but it won't affect the A cup!

You can change the Cat, using your new B reference (copied directly from A), but you can't change A.

What the heck does that mean?

You can change the object A refers to, but you can't take the A reference variable and do something to it -- like redirect it to reference a different object, or null.

So if you change the B reference (not the Cat object B refers to, but the B reference itself) you don't change A. And the opposite is true.

So...

Cat A = new Cat();
doStuff(A);

void doStuff(Cat B) {

   B = new Cat(); //did NOT affect the A reference
}

Doing this simply "points" B to control a different object. A is still happy.

So repeat after me:

Java is pass-by-value.

(OK, once again... with feeling.)

Java is pass-by-value.

For primitives, you pass a copy of the actual value.

For references to objects, you pass a copy of the reference (the remote control).

You never pass the object. All objects are stored on the heap. Always.

Now go have an extra big cup of coffee and write some code.

Printable Version