aspose file tools*
The moose likes Java in General and the fly likes Interesting problem in Java with pass by reference Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Interesting problem in Java with pass by reference" Watch "Interesting problem in Java with pass by reference" New topic
Author

Interesting problem in Java with pass by reference

Bill White
Ranch Hand

Joined: Oct 27, 2002
Posts: 82
I understand that when you pass an object in Java it is automatically passed by reference. So any change made in the method it was passed to is made to the object that was passed.
Here is some test code:
Client one = client_ImageManager1.createClient(clientOne, clientOneMac);
Client two = client_ImageManager1.createClient(clientTwo, clientTwoMac);
Client three = one;
System.out.println(one.equals(three));
three.setDescription("TEST");
System.out.println(one.getDescription());
client_ImageManager1.changeRef(three);

System.out.println(one.getDescription());
System.out.println(three.getDescription());
here is changeRef()
public void changeRef(Client test)
{
Client t = test;
t.setDescription("F");
t = null;
test = null;
}
my expected output was: true Test then a NPE
what I got was: true test F F
So, is this because the Garbage Collector has not cleaned up the memory yet? If so, that seems BAD.
Looking to the experts to clarify this.
Thank You
Cindy Glass
"The Hood"
Sheriff

Joined: Sep 29, 2000
Posts: 8521
No - it is doing what it is supposed to do.
You have 5 variables here:
one
two
three
test
t
but you only have 2 objects:
The one that "one" originally referenced and the one that "two" originally referenced.
one refereces obj1
two references obj2
then you point variable three at the same object as variable one so
three references obj1
You set the description of obj1 to 'test' and print it out.

The you pass a copy of the reference that three is holding to your method - so you pass in a reference to obj1
test references obj1
Then you create variable t and point it at the same object that test is referencing so
t references obj1
You set the description of the object that t is referecing (obj1) to 'F'.
Then you free up variable test and variable t. That does not get rid of the object that they reference because "one" still holds a referecne to obj1.
When you return from you method you print the description of the object referenced by variable "one" which is obj1 which now holds an 'F'.
Then you print the description of the object referenced by variable "three" which is also obj1 which of course still holds an 'F'.
[ April 23, 2003: Message edited by: Cindy Glass ]

"JavaRanch, where the deer and the Certified play" - David O'Meara
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451

I understand that when you pass an object in Java it is automatically passed by reference.

Not true. All paramaters in Java are passed by value. Whether it is a primitive like int or a reference to an Object, a copy is passed into the method. It is important to remember that a reference is not an object, it is a means of locating an object only, sort of like a C pointer, but bound to a single object.


Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius - and a lot of courage - to move in the opposite direction. - Ernst F. Schumacher
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2861
    
  11

No, it has nothing to do with the garbage collector. You are right though that objects are passed by reference in Java. Let's look at it step by step.
You create a Client object and set a reference to it:
Client one = new Client();
(I'm simplifying here for clarity.)
You then call a method using your Client object as parameter. This creates a second reference to the same client object.
changeRef(one);
You are not passing a reference to "one", but to the object that "one" refers to. You can also think of it as passing "one" by value, but "one" is itself a reference.
Inside the method, you create a third reference to the object.
Client t = test;
Finally, you set the second and third reference to null. That doesn't change the object in any way. It just means that "test" and "t" no longer refer to it. In this case, that is sort of meaningless because the method returns immediately. When that happens, those references cease to exist anyway. However, "one" still exists and still refers to the same client object. Nothing you can do in the method can change that. The Client object will not be garbage collected until all references to it are either gone or pointing somewhere else.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2861
    
  11

Wow, a triple simulpost. We obviously need more people asking questions about first principles in here!
Joshi Thomas
Greenhorn

Joined: Oct 03, 2002
Posts: 7
Objects are also passed by value. You can change the state of the object (often confused with passing with reference) but you cannot set the object set to null. Java does not support passing objects by reference.


SCJP<br />SCWCD
Bill White
Ranch Hand

Joined: Oct 27, 2002
Posts: 82
Micheal,
Thank you, I stand corrected. The value of the reference is passed.
But in the end, the same thing as "Passing by reference" happens. That is, changes made in the method are reflected onto all objects that point to that reference. Correct?
Nilesh Pereira
Ranch Hand

Joined: Apr 14, 2003
Posts: 53
Just to clarify things:
Java copies and passes the reference by value, not the object. Thus, method manipulation will alter the objects, since the references point to the original objects. But since the references are copies, swaps will fail.
Bill White
Ranch Hand

Joined: Oct 27, 2002
Posts: 82
Yes. I tested this further with
Client a = new Client();
Client b = a;
b.setDescription("Some String");
a = null;
System.out.println(b.getDescription());
And got back Some String. For 2 years I have been programming Java professionaly under the assumption that b would have been set to null.
Thankfully, I have yet to be bit by this. I now have a new understanding and appreciation of how Java deals with passing objects and the consequences of such.
Thank You all.
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451

But in the end, the same thing as "Passing by reference" happens.

Not exactly, as Nilesh and Joshi point out. Yes, you can certainly change the state of the object referenced in the mehtod, but changing the value of the parameter inside the method has no effect on the reference in the calling object, which it would in a true call by reference, like using the & (address of) operator or a pointer in C.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I agree with Michael, Nilesh and Joshi. If Java were truly "pass by reference" (as the term is understood by users of other laguages such as C) then you'd be able to write code like this

and you'd see
x = bar
y = foo
But you don't, since the swap method only gets copies of the values of the references - it can't change the original references themselves. And since "foo" and "bar" are immutable strings, there is absolutely no way you can rewrite swap() to exchange the data between x and y. If Java were really "pass by reference", the swap() method would work.


"I'm not back." - Bill Harding, Twister
Joel McNary
Bartender

Joined: Aug 20, 2001
Posts: 1824

By these definations, C does not implement pass by reference either! The C method to do Jim's code:

This will produce the same output as in Java (x = foo, y = bar) since the swap function gets a copy of the pointers and not the original pointers themselves.
This is understood to be "pass by reference" in C, since you could modify the value of the strings in the functions. Why is this not "pass by reference" in Java? Or am I misunderstanding "pass by reference" in C?
[ April 23, 2003: Message edited by: Joel McNary ]

Piscis Babelis est parvus, flavus, et hiridicus, et est probabiliter insolitissima raritas in toto mundo.
Nilesh Pereira
Ranch Hand

Joined: Apr 14, 2003
Posts: 53
Well, if you used references it would've worked
Your swap method declaration should read:
void swap(void &a, void &b)
...
[ April 23, 2003: Message edited by: Nilesh Pereira ]
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Java always does pass by value. C# supports pass by value as the default and pass by reference.
Look at this:

Guess what prints... "Java".
The C# version:

This will print C#.
[ April 23, 2003: Message edited by: Thomas Paul ]

Associate Instructor - Hofstra University
Amazon Top 750 reviewer - Blog - Unresolved References - Book Review Blog
Joel McNary
Bartender

Joined: Aug 20, 2001
Posts: 1824


and call swap(&x, &y) to get the x = bar y = foo result. This technique is dereferencing the variables, which is not directly supported by Java, but my assertion is still that my prior attempt is "pass by reference".
[ April 23, 2003: Message edited by: Joel McNary ]
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Originally posted by Joel McNary:
This technique is dereferencing the variables, which is not directly supported by Java, but my assertion is still that my prior attempt is "pass by reference".

Pass by reference is what C# does in my example above. Java can not do anything like that.
Joel McNary
Bartender

Joined: Aug 20, 2001
Posts: 1824

Originally posted by Thomas Paul:

The C# version:
<snip>
This will print C#.
[ April 23, 2003: Message edited by: Thomas Paul ]

Interesting example. Does this mean that C does not support pass by reference as understood by C#? Or is the ability to dereference your references required to be termed "pass by reference"?
[ April 23, 2003: Message edited by: Joel McNary ]
Nilesh Pereira
Ranch Hand

Joined: Apr 14, 2003
Posts: 53
Sorry, that was C++ syntax. My bad!
In C, you pass the reference in your
swap method invocation, and use the
pointer in your swap method.
for example:

The bottom line is that in C/C++ you can choose to pass by value OR by reference... in java you can ONLY pass by value.
[ April 23, 2003: Message edited by: Nilesh Pereira ]
Jamie Robertson
Ranch Hand

Joined: Jul 09, 2001
Posts: 1879

I found that this article has a good explanation.
Jamie
Joel McNary
Bartender

Joined: Aug 20, 2001
Posts: 1824

Hmm...I had no idea that C++ supported that syntax. I've never used it!
When I code in C/C++, I never create objects; in create pointers to objects and then new / malloc the objects themselves. I then pass my pointers to functions. I had always believed that this was termed "pass by reference" because I was passing not the Object itself but rather a reference to the object. This is exactly the same thing that is done in Java, except that we don't have the option of creating an object directly; we have to use new.
Because of how I code my C/C++, I've never been confused as to what Java is doing when I work with objects. I was confused because they term "pass by value" doing the same thing in Java that I term "pass by reference" in C/C++.
Examples: (Given a class SomeList which can add a string (char*) and randomizes the elements through a function randomizeMe)
1:

So my question: In this example, is this pass by value or reference? In Java, the analous code replaces "->" with "." and drops the "*"s and is termed "pass by value," which leads me to believe that what I am doing in my above example is also "pass by value", even though I thought that it was "pass by reference"
2:

This is unquestionably pass by reference; or at least how I learned pass by reference. The list will be randomized.
3:

and this is pass by value. The list would never be randomized.
If 2 is pass by reference, why isn't 1? And if 1 is what Java does, why don't we call what Java does pass by reference?
As I said, I'm not confused by what happens, just confused about why we call it what we do....
Joel McNary
Bartender

Joined: Aug 20, 2001
Posts: 1824

"and this is pass by value. The list would never be randomized."
Of couse, I meant that the List in the main method would never be randomized.
Thanks for the article, Jamie. It does state that C does not support treu pass by reference, but rather can simulate it through & and dereferencing in the called method.
Since I've never used the C++ ability to declare a &x in my formal parameters, I guess I've never done true pass by reference!
Nilesh Pereira
Ranch Hand

Joined: Apr 14, 2003
Posts: 53
Apparently I misread your post. Sorry.
[ April 23, 2003: Message edited by: Nilesh Pereira ]
 
wood burning stoves
 
subject: Interesting problem in Java with pass by reference