Link to home
Start Free TrialLog in
Avatar of gudii9
gudii9Flag for United States of America

asked on

pass by value in java

Hi,

i was working on this example

http://www.avajava.com/tutorials/lessons/do-java-methods-use-pass-by-reference-or-pass-by-value.html?page=2


I have not understood the output clearly.
a (in main) is: 1
a (in doSomething) is: 2
a (in main) is: 1

myTest's x (in main) is: 1
myTest's x (in doSomething) is: 2
myTest's x (in main) is: 2

s (in main) is: str1
s (in doSomething) is: str2
s (in main) is: str1

myTest2's x (in main) is: java.lang.NullPointerException

myTest3's x (in main) is: 1
myTest3's x (in doSomethingAndNull) is: 3
myTest3's x (in main) is: 3



I wonder how i got as below for the String argument passing call in the method.

s (in main) is: str1
s (in doSomething) is: str2
s (in main) is: str1


I thought it supposed to be

s (in main) is: str1
s (in doSomething) is: str2
s (in main) is: str2

similar to object references(since String is also an object)

please advise
Any links resources ideas highly appreciated. Thanks in advance
Avatar of CPColin
CPColin
Flag of United States of America image

I started typing up an explanation for what happened, then noticed that the tutorial you linked already details what's going on. Is there a specific part of that explanation that you're having trouble with?
SOLUTION
Avatar of Guy Hengel [angelIII / a3]
Guy Hengel [angelIII / a3]
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dpearson
dpearson

The first example in the code for an object sets a value like this:

myTest.setX(2);

This doesn't change what "myTest" is referring to.  It's changing the value *inside* the object it is pointing to.

myTest = anotherObject ; // This would change what myTest is pointing to

Now compare that to the string situation:

s = "str2";     // This changes what "s" refers to, not the value stored *inside* the String object.  See how this looks more like the "myTest = anotherObject" case?

If you wanted to get the same sort of behavior as for the object example, you'd need a class like this:

class MyStringContainer {
    private String x ;
    public void setX(String value) { x = value ; }
    public String getX() { return x ; }
}

Then:

      public static void main(String[] args) throws IOException {
                MyStringContainer myTest = new MyStringContainer() ;
            System.out.println("\nmyTest's x (in main) is: " + myTest.getX());
            doSomething(myTest);
            System.out.println("myTest's x (in main) is: " + myTest.getX());
      }

      public static void doSomething(MyStringContainer myTest) {
            myTest.setX("new string");
            System.out.println("myTest's x (in doSomething) is: " + myTest.getX());
      }

Now the string will change value - because

myTest.setX("new string");

is changing the value inside the "myTest" object, rather than changing what myTest refers to.

Making better sense yet?

Doug
Guy,

The value that is copied is the address of the object, not the object itself. In this case, the doSomething() method assigns a new address to the object reference that was passed in, without changing the original object at all.
Java Supports Pass by value,
For Primitive data type it would be Pass by value...
For Object, it would be Pass by value of reference...
Avatar of gudii9

ASKER

" When we do an assignment operator with a String reference, we are actually creating a new String object for the reference to point to. Strings is Java are "immutable", which means that the value of a String object can't change after the String has been created. So, the call to 's = "str2";' actually creates a new String object for the String reference 's' in the method to point to. So, the 's' reference in the doSomething() method points to a new String object with the value "str2", but the 's' reference in the main() method still points to the String object with value "str1".

Makes more sense. But how same 's' is assigned to "str1" in main() as below
public class Test {

      public static void main(String[] args) throws IOException {
...
            String s = "str1";
            System.out.println("\ns (in main) is: " + s);
            doSomething(s);
            System.out.println("s (in main) is: " + s);
...
      }

 also s is assigned to "str2" inside other method as below
public static void doSomething(String s) {
            s = "str2";
            System.out.println("s (in doSomething) is: " + s);


please advise
String s is a reference to an object (a pointer).

So you are free to move it to point to any object/String that you like.  But changing your reference is NOT the same as changing the object.

String s = "hello" ;
String t = s ; // t points to "hello" as well.

Now:
s = "goodbye" ;  // Doesn't affect the string "hello".  Just points to "goodbye" now.

t is still pointing to "hello" (because we didn't change the object at all).
s is now pointing to "goodbye"

Any good?

Doug
Avatar of gudii9

ASKER

but changing where the reference in the method points to doesn't change where the original reference outside of the method points to."


t is still pointing to "hello" (because we didn't change the object at all).
s is now pointing to "goodbye"


so s is pointing to goodbye not hello in same logic s  also should point to str2 not str1 after call to doSomething() method call?

so s can simulatneously refer to str1 in main method and to str2 inside the doSomething() method.



May be some pictorial representation helps a lot. Please advise
so s can simulatneously refer to str1 in main method and to str2 inside the doSomething() method.

Yes that's right because that's actually two different variables.  Calling them both 's' is actually just confusing the situation.

The original code was:
public static void main(String[] args) throws IOException {
		String s = "str1";
		doSomething(s);
	}

	public static void doSomething(String s) {
		s = "str2";
	}

Open in new window


This code is actually *identical* to this code:
public static void main(String[] args) throws IOException {
		String s = "str1";
		doSomething(s);
	}

	public static void doSomething(String another) {
		another = "str2";
	}

Open in new window


which maybe makes it more obvious that the "String s" in main is not the same as the "String another" in doSomething() and that setting

another = "str2"

has no effect on s.

Doug
Avatar of gudii9

ASKER

I see the example as below

import java.io.IOException;

public class Test {

	public static void main(String[] args) throws IOException {

		int a = 1;
		System.out.println("a (in main) is: " + a);
		doSomething(a);
		System.out.println("a (in main) is: " + a);

		MyTest myTest = new MyTest();
		System.out.println("\nmyTest's x (in main) is: " + myTest.getX());
		doSomething(myTest);
		System.out.println("myTest's x (in main) is: " + myTest.getX());

		String s = "str1";
		System.out.println("\ns (in main) is: " + s);
		doSomething(s);
		System.out.println("s (in main) is: " + s);

		try {
			MyTest myTest2 = new MyTest();
			myTest2 = null;
			System.out.print("\nmyTest2's x (in main) is: ");
			System.out.println(myTest2.getX());
		} catch (RuntimeException e) {
			System.out.println(e);
		}

		MyTest myTest3 = new MyTest();
		System.out.println("\nmyTest3's x (in main) is: " + myTest3.getX());
		doSomethingAndNull(myTest3);
		System.out.println("myTest3's x (in main) is: " + myTest3.getX());

	}

	public static void doSomething(int a) {
		a = 2;
		System.out.println("a (in doSomething) is: " + a);
	}

	public static void doSomething(MyTest myTest) {
		myTest.setX(2);
		System.out.println("myTest's x (in doSomething) is: " + myTest.getX());
	}

	public static void doSomething(String another) {
		another = "str2";
		System.out.println("s (in doSomething) is: " + another);
	}

	public static void doSomethingAndNull(MyTest myTest3) {
		myTest3.setX(3);
		System.out.println("myTest3's x (in doSomethingAndNull) is: " + myTest3.getX());
		myTest3 = null;
	}

}

Open in new window


I got output as below

a (in main) is: 1
a (in doSomething) is: 2
a (in main) is: 1

myTest's x (in main) is: 1
myTest's x (in doSomething) is: 2
myTest's x (in main) is: 2

s (in main) is: str1
s (in doSomething) is: str2
s (in main) is: str1

myTest2's x (in main) is: java.lang.NullPointerException

myTest3's x (in main) is: 1
myTest3's x (in doSomethingAndNull) is: 3
myTest3's x (in main) is: 3



which makes more sense as it is new string.

Also



class MyStringContainer {
    private String x ;
    public void setX(String value) { x = value ; }
    public String getX() { return x ; }




      public static void main(String[] args) {
                MyStringContainer myTest = new MyStringContainer() ;
            System.out.println("\nmyTest's x (in main) is: " + myTest.getX());
            doSomething(myTest);
            System.out.println("myTest's x (in main) is: " + myTest.getX());
      }

      public static void doSomething(MyStringContainer myTest) {
            myTest.setX("new string");
            System.out.println("myTest's x (in doSomething) is: " + myTest.getX());
      }

}

Open in new window


When i run above code i get output

myTest's x (in main) is: null
myTest's x (in doSomething) is: new string
myTest's x (in main) is: new string



I see String value is getting effected in above example you mentioned.


more obvious that the "String s" in main is not the same as the "String another" in doSomething() and that setting


I wonder why java has string method calling mechanism similar to Object when both concepts are 360 degrees apart.It is confusing. What are the practical uses of pass by value and pass by reference. I do not know any other programming language. I wonder what is big deal about this concept in practical stand point. please advise
What are the practical uses of pass by value and pass by reference. I do not know any other programming language. I wonder what is big deal about this concept in practical stand point

Almost all modern languages use pass by value.  Pass by reference is generally a lot more complicated and error prone.  C++ supports it but only if you deliberately ask for it (in the way you pass the parameters).

Pass by reference is something of a throw-back to the days when memory was scarce and CPUs not very powerful.  You could make some algorithms more efficient by using pass by reference.  But today we know that CPU cycles aren't usually the big challenge in developing software - it's making sure that the program works correctly that's the big challenge.  And pass by value makes it easier to have a working program, so it's preferred i modern languages.  (If you don't understand why - just take that on trust).

As long as you fully understand how pass by value works, you should be fine to ignore the concept of pass by reference.  You could program for many years and never need to understand the distinction.

Doug
Avatar of gudii9

ASKER

primitive and strings are clear(which are behaving same by not changing values after doSomething method call in main). But with objects I have not understood below statement in the link clearly (by changing values of myTest3.getX after doSomething method call in main))

Our output is shown here. We can see that we changed the value of the myTest object's x field. In proper terms, I guess we should say that we changed the x field of the object that the myTest reference in our main method points to.

myTest's x (in main) is: 1
myTest's x (in doSomething) is: 2
myTest's x (in main) is: 2


what it specifically mean
say that we changed the x field of the object that the myTest reference in our main method points to

May be a picture is helpful to visualise x field of object (myTest) in main method of other java class(Test.java)
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gudii9

ASKER

myOtherReference.setX(2) ;
System.println(myOtherReference.getX()) ; // Prints 2
System.println(mytest.getX()) ; // Prints 2 <-- Make sure you understand this

that is true since both references point to same object.

Finally all makes sense. thank you very much.