I am working as a senior engineer with a telecom major in India. In java, I have around 6 Yrs of experience which has only increased my hunger for learn. My other hobbies include playing Table Tennis, Badminton and Carom. I also love watching all kind of Hollywood movies. In fact, I am a big fan of Steven Spielberg, James Cameron and Tom hanks. Lokesh has posted 2 posts at DZone. You can read more from them at their website. View Full User Profile

Java is Pass by Value and Not Pass by Reference

03.07.2013
| 19622 views |
  • submit to reddit

There has been a good amount of debate on whether "Java is pass by value or pass by reference?". Well, lets conclude it last time, Java is pass by value and not pass by reference. If it had been pass by reference, we should have been able to C like swaping of objects, but we can't do that in java. We know it already, right? When you pass a instance to a method, its memory address are copied bit by bit to new reference variable, thus both pointing to same instance. But if you change the reference inside method, original reference will not get chnage. If it was pass by reference, then it would have got changed also.

To prove it, lets see how memory allocations happen in runtime. It should solve the slightest doubts, if any. I am using following program for demonstration of the concept.

public class Foo
{
	private String attribute;
	
	public Foo (String a){
		this.attribute = a;
	}
	public String getAttribute() {
		return attribute;
	}
	public void setAttribute(String attribute) {
		this.attribute = attribute;
	}
}

public class Main
{
     public static void main(String[] args){
          Foo f = new Foo("f");
          changeReference(f); // It won't change the reference!
          modifyReference(f); // It will change the object that the reference variable "f" refers to!
     }
     public static void changeReference(Foo a) {
          Foo b = new Foo("b");
          a = b;
     }
     public static void modifyReference(Foo c) {
          c.setAttribute("c");
     }
}



Lets see what happen on runtime step by step :

1) Foo f = new Foo("f");

This statement will create a instance of class Foo, with 'attribute' initialized to 'f'. The reference to this created instance is assigned to variable f;



2) public static void changeReference(Foo a)

When this executes then a reference of type Foo with a name a is declared and it's initially assigned to null.



3) changeReference(f);

As you call the method changeReference, the reference a will be assigned to the object which is passed as an argument.



4) Foo b = new Foo("b"); inside first method

This will do exactly the same as in fisrt step, and will create a new instance of Foo, and assign it to b;



5) a = b;

This is the important point. Here, we have three reference variables and when statement executes, a and b will point to same instance created inside the method. Note: f is unchanged and it continuely pointing to instance, it was pointing originally. NO CHANGE !!



6) modifyReference(Foo c);

Now when this statement executed a reference, c is created and assigned to the object with attribute "f".



7) c.setAttribute("c");

This will change the attribute of the object that reference c points to it, and it's same object that reference f points to it.



I hope that this explanation was enough clear to make your understanding better, if it was not already.

Happy Learning !!

Published at DZone with permission of its author, Lokesh Gupta. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Siryc Pups replied on Thu, 2013/03/07 - 5:12am

 Java is pass(call) by sharing
Call by sharing

Lokesh Gupta replied on Thu, 2013/03/07 - 5:59am in response to: Siryc Pups

 It also says that.. "The description "call-by-value where the value is a reference" is common (but should not be understood as being call-by-reference);"

So, it is ultimately call by value... right??

Robert Saulnier replied on Thu, 2013/03/07 - 8:38am

In step 2, the param a is a local variable. Local variables are not assigned default values. Param a is undefined till a value is assigned to it.

Tom Hartwell replied on Thu, 2013/03/07 - 2:04pm in response to: Robert Saulnier

While param a is local, it is not undefined and it does have a value. Its value is a reference to the Foo object created in the main method. Confusion is caused because the 'value' in the pass by value is a reference to the Foo object, but not the same reference as the one created in the main method.

Robert Saulnier replied on Thu, 2013/03/07 - 3:30pm

I didn't say it doesn't get a value, it gets assigned a value in step 3. I said in step 2, it is not assigned null. Step 2 should read:

2) public static void changeReference(Foo a)

When this executes then a reference of type Foo with a name a is declared and it's initially assigned to null.

When a method is called, a new Frame is created with an array of local variables. There is no mention of default values for those variables:

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.6.1

Lokesh Gupta replied on Thu, 2013/03/07 - 6:58pm in response to: Robert Saulnier

I do agree.... updated the post.

Tom Hartwell replied on Fri, 2013/03/08 - 3:55pm in response to: Tom Hartwell

@Robert, thanks for the clarification and the link.

Anilchandra Noo... replied on Fri, 2013/03/08 - 6:50pm

The Spec Says it is PassByValue. No  debate.

Good explanation.

 

Zlatan Kadragic replied on Mon, 2013/03/11 - 8:47am

Java is exactly the same as C, so I don't understand this sentence:

<cite>If it had been pass by reference, we should have been able to C like swaping of objects, but we can't do that in java. </cite>

In C swapping is not possible to do directly.


Mark Alexandre replied on Thu, 2013/03/14 - 7:06pm

Mr. Gupta has drawn some nice diagrams that may help out any Java beginner who is confused about how parameter passing works.  However, this whole never-ending debate about whether Java is "pass by value" or "pass by reference" is ultimately rather vacuous.

Primitives are of course passed by value in Java, copied exactly as they are by an assignment statement.  Object instances are likewise passed through to method parameters exactly as if there had been an assignment of each actual argument to the corresponding parameter, that is, by creating a new reference to the same object instance.

Thus we see that Java parameter passing is quite easily understood as "pass (in) by assignment," a simple concept that follows straightforwardly from an understanding of how assignment works in the language.  The argument over "by value" versus "by reference" is a tedious exercise in semantics that attempts to shoehorn the language into either of two basic models commonly taught in a Programming Languages 101 class, neither of which is precisely applicable to Java.

Lokesh Gupta replied on Thu, 2013/03/14 - 11:15pm in response to: Mark Alexandre

 Well said..

Roger Persson replied on Fri, 2013/03/15 - 6:04am

rehashing this old worn subject once again? :)

As someone already pointed out, C is just a much call-by-value as Java is. Thats why you need the ampersand -- to pass a reference... BY VALUE.

The confusion comes from java's object implementation which is an implementation-by-pointers/references. Because of this implementation, to be TRULY call-by-value it would need to DEEP-COPY all parameters in method-calls.

Robert Saulnier replied on Fri, 2013/03/15 - 8:28am in response to: Zlatan Kadragic

Java is not the same as C. You cannot swap in Java, but you can in C:

http://stackoverflow.com/questions/8403447/swapping-pointers-in-c-char-int

Zlatan Kadragic replied on Fri, 2013/03/15 - 1:42pm

You can swap in C using exactly  the same trick as in Java: do the "swapping" using reference/pointer to the value you are "swapping".  C just lets you do that easier because you can get the pointer from the value. In Java there is no such operator, so you need to make your own wrapper or use org.apache.commons.lang3.mutable

You just can't swap directly arguments in Java and C, that's why it can't be called pass by reference. For example Pascal has pass by reference if you use VAR keyword in formal parameter of procedure.

Robert Saulnier replied on Fri, 2013/03/15 - 2:23pm in response to: Zlatan Kadragic

You don't need any tricks to swap pointers in C, but in Java it can't be done. Apache Commons won't help you here.

Can you implement the method swap below so that the main method will print?

Two

One

public class Swap {

    public static void main(String[] args) {
        String one = "One";
        String two = "Two";
        
        swap(one, two);
        
        System.out.println(one);
        System.out.println(two);
    }

    private static void swap(String a, String b) {
        //?
    }
}

Zlatan Kadragic replied on Sat, 2013/03/16 - 3:04am in response to: Robert Saulnier

It is not possible to implement such direct swap, as I have already written. But try to do the same in C:

#include <stdio.h>

void swap(char* stringA, char* stringB);

int main()
{
    char* one = "One";
    char* two = "Two";
    
    swap(one, two);
    
    printf("%s\n", one);
    printf("%s\n", two);

    return 0;
}

void swap(char* stringA, char* stringB) {
    // ?
}



Robert Saulnier replied on Sat, 2013/03/16 - 8:59am in response to: Zlatan Kadragic

The swap method needs to take a pointer to a char*.

#include <stdio.h>

void swap(char** a, char** b) {
    char* t = *a;
    
    *a = *b;
    *b = t;
}

int main(int argc, char** argv) {
    char* one = "One";
    char* two = "Two";
    
    swap(&one, &two);
    
    printf("%s\n", one);
    printf("%s\n", two);
    
    return 0;
}

Zlatan Kadragic replied on Sat, 2013/03/16 - 4:41pm in response to: Robert Saulnier

Pointer to pointer, so that the target pointer could be changed. So then why I am not allowed to use reference to reference, so that the target reference could be changed? But you refused that kind implementation (the easiest is by using commons wrapper classes). So let me use my knowledge of Logic. I can use reductio ad absurdum. So you are telling that in C it is OK to use pointer indirection and you call that pass by reference , but for Java you are telling that indirection is not pass by reference. So the same statement is in one case true, in other false which is absurdum.

Simply telling you are cheating by using more "*" than it is allowed :) But officially it is known as Straw Man argument, and it is very popular in politics. 

It last my Logic study has applicability, thanks to my good continental high school education (grammar/gymnasium).


Robert Saulnier replied on Mon, 2013/03/18 - 9:52am in response to: Zlatan Kadragic

You initially stated:

In C swapping is not possible to do directly.

I demonstrated that swapping is possible. How is this a straw man? Of course I used pointers, because C has them. If Java had pointers, swapping would probably be possible too.

And now let's check your logic. I never mentioned "pass by reference", you did :) I avoid using the term "pass by reference" since its meaning in Java gets confused.

The reason I dismissed wrapper classes is because we're no longer talking about the same thing. Wrapper classes can swap fields, but this discussion is about swapping local variables.

Roger Persson replied on Wed, 2013/03/20 - 4:11am in response to: Robert Saulnier

"...You don't need any tricks to swap pointers in C..."

Yes you do, the "trick" is the "address" operator (&).
But that has nothing to do with calling conventions. They are essentially the same.

In Java, you can use e.g. the Holder<T> datatype to achieve similar effect as the address operator.

Robert Saulnier replied on Wed, 2013/03/20 - 8:57am in response to: Roger Persson

I rarely do C programming, but I didn't think using "&" a trick. If it is a trick, I think it's a trick that's used a lot.

And again, I'm not discussing using wrappers or holders. The equivalent example of using a Holder in Java would be a struct in C. I'm not talking about swapping fields.

Just about every class in Java is a holder/wrapper of other fields. You don't need anything special to implement a wrapper in Java. All JavaBeans are wrappers of other fields, Date is a wrapper of a long,  String is a wrapper around a char[]. The Atomic classes are wrappers. A 1-length array is a wrapper for a reference, and so on.

A "trick" in Java would be to swap the String's char[] using reflection. But this is still swapping a field, not the Java reference.

Mujahid Masood replied on Tue, 2013/07/02 - 9:06am

  class Animal1 {
  String name = "animal";
}
 class Dog2 extends Animal1{
  String name = "Dog";
}
 class Main2 {

 
 public static void main(String[] args) {
   
  Animal1 animal = new Dog2();
  Dog2 dog = new Dog2();
 // Dog2 dog2 = (Dog2) new Animal1();
 
  System.out.println("Animal name :"+animal.name);
  System.out.println("Dog name :"+dog.name);
  //System.out.println("Dog2 name: "+dog2.name);
 
 }


Hi,

 Can anyone please elaborate pass by value and pass by reference concept here. Because from this piece of code I see its pass by reference?


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.