views:

180

answers:

6

Hi,
I am confused in the following:
In C++ we can pass a parameter to a function by reference (having declared it as a pointer or reference variable) and if we modify it inside the function, the changes are reflected to the caller when the function returns.
This is not happening in java and I am not sure I understand why.

E.g. this is a method from an object X

public boolean aMethod(int id, myClass aClass)
{
   //do some logic
   aClass = new MyClass();
   //configure argument object aClass
   return true;
}

In the calling code:

//some code processing
myClass obj = null;
if(X.aMethod(2,obj))
{
  obj.methodA();//start using the object
}

I use it in C++, i.e. to return a result that notifies that the function parameter can be used, but in java this does not work.
I enter the if(X.aMethod(2,obj)) branch but the obj is null. Why is it null?
Haven't I assigned a memory address from the heap using new inside the method aMethod(int id, myClass aClass)? Am I not passing the "address" of obj in the function? I was expecting to have the obj properly constructed and usable in the calling code. Have I misunderstood something concerning memory in java?

+1  A: 

Java cannot do "pass by reference".

Java uses "pass by value".

Yin Zhu
+16  A: 

Java passes everything by value - including references.

What this means is that if you pass an object, you can modify properties of that object, and they will persist after you return, but you can't replace the object in its entirety with a completely new object, because you can't actually modify the reference - only what the reference points to.

Before your aClass = line:

Outside the function:

    obj ---> <foo>

Inside the function:

    aClass ---> <foo>

After your aClass = line:

Inside the function:

    aClass ---> <bar>

Outside the function:

    obj ---> <foo>

The key thing to notice here is that aClass doesn't point to obj - it points to <foo>. You're not passing the address of obj, you're passing the address of what obj points to. Thus, when you change what aClass points to, that doesn't touch obj.


As an alternative way of thinking about it:

In Java,

Bar foo = new Bar();

is equivalent to C++,

Bar *foo = new Bar();

Thus when you pass foo to a function, you're not passing the address of foo - you're passing the address of the allocated object. Java doesn't have the &-operator style pass-by-reference that C/C++ do.

Amber
`new Bar()`, you mean. :)
Jonathan Grynspan
@Jonathan oops, typo. :)
Amber
A: 

consider your object arguments (in Java) passed as such (illustrated in C++):

void method(TObject* arg);
Justin
Should be `void method(TObject*` ?
Ishtar
Justin
@Ishtar part 2: in c++, pass by value == pass a copy of the object. there is no copy with Java here. so passing a Java object in c++ syntax is analogous to: `void method(TObject* arg);`
Justin
Ishtar
@Ishtar no problem. in fact, my initial response lacks detail - so it's good that it has been clarified now. thanks =)
Justin
+2  A: 

In C++ what would happen if you did this:

 void myFunct( int * pInt) {
     pInt = // something;
 }

 // caller
 int x;
 int * myPointer = & x;
 myFunc(myPointer);
 // where does myPointer point now? 

the assignment inside myFunc has no effect on the caller's pointer. Now if myFunct took instead pointer to the pointer

 void myFunct( int ** ppInt) {
     *ppInt = // something;
 }

or a reference to the pointer then you would see a change in caller, and that is what I suppose you have been doing.

In Java

 void myFunct (Integere anInteger) {
       // anInteger is  reference to whatever is passed
       anInteger = new Integer(99); // no effect on caller
 }

we do indeed pass references to the function, anInteger above is a reference to an object owned by the caller, but anInteger is a value local to the method assigning to it is the same as assigning to a pInt in the first example, no effect on the caller.

djna
+1  A: 

The comment in your example suggest that the method aMethod exists to configure the object. So instead of passing in null, how about instantiating the object first and then pass it in. Alternatively, you can make the method return the object intead, like so:

public boolean aMethod(int id)
{
  myClass aClass = new MyClass();
  return myclass;
}

And:

myClass obj = X.aMethod(2);
if(obj != null)
{
  obj.methodA();//start using the object
}

Alternatively, I prefer to make it a convention that aMethod should always return a valid object. If it's not possible, for example because of a mistake in the configuration, make the method throw an exception instead.

RichN
+1  A: 

Check out my article on this, "Java is Pass By Value, Dammit"

http://javadude.com/articles/passbyvalue.htm

Scott Stanchfield
@Scott:Very good article! Thanks a lot!
My pleasure! Glad you liked it!
Scott Stanchfield