2

I would like to ask a really simple question. I am just passing a String object to a function but the result is weird. I supposed that because I am passing an object(by reference) the result should have be " Here" and not "Hello". Why is this happening?

public class MainStr
{

/**
 * @param args
 */
public static void main(String[] args)
{
    String str = "Hello!";
    System.out.println(str);
    changeString(str);
    System.out.println(str);


}

static void changeString(String str)
{
    str=" HERE";
}

}

Thanks.

EDITED:

public class MainStr
{

String str;
/**
 * @param args
 */
public static void main(String[] args)
{
    MainStr ms = new MainStr();
    ms.str = "Hello!";
    System.out.println(ms.str);
    changeString(ms);
    System.out.println(ms.str);


}

static void changeString(MainStr ms)
{
    ms.str=" HERE";

}

}

If that is the case then why if I pass it inside a wrapper object is working? The wrapper object it is not by reference?

PS: Why this is working that way? String is an object. Why do I need another wrapper Object to change an OBJECT! What if I want to pass something by reference? Is that possible?

glarkou
  • 7,023
  • 12
  • 68
  • 118
  • Java is working with references with all complex types. Strings and all used defined types are all represented by references. You can think about reference as a C++ pointer you can't access value of. – Suzan Cioc Feb 07 '12 at 21:14
  • @salamis Remeber Java is pass-by-value always! The formal parameter (which is str in method changeString) is simply a copy of the reference that points to the memory location where "Hello!" is. Therefore when you assign "HERE" now instead of pointing at "Hello!" points to "HERE" while the original is unchanged. The "HERE" will be garbage collected. – MalsR Feb 07 '12 at 21:22

6 Answers6

7

Java passes object references by value this means when you call a function the following happens.

 String origStr = "Some String"

 // origStr -> "Some String "

When the object is passed to the value it looks like this

 //origStr -> "Some String " <- passedStr

Then in the function you reset what passedStr points to

 //origStr -> "Some String "
 //passedStr -> "Other String"

The original string still refers to "Some String" but the copy of it now refers to "Other String"

When you return from the function the original string reference still points at "Some String"

// EDIT: Why can you modify objects referred to by another object?

Lets say I have StringWrapper, which is a class which contains a string.

To java that looks like this

origStr -> strWrpA -> "Some String"

When you pass it to a function the following happens just like above

origStrWrp -> strWrpA -> "Some String"
passedStrWrp --/^

Notice how both variables point at strWrpA in memory. Now if i decided to modify the strWrpA.myString Java will follow the pointer to the actual string in the wrapper. The pointer to strWrpA will remain unchanged. This means I can change the contents of the object even though I'm accessing it through a copy of the original reference.

                        "Some String "
origStrWrp -> strWrpA -> "I got Changed!"
passedStrWrp --/^

You would have the same problem as you have without a wrapper if you did this

//Does Nothing
function (origStrWrp)
{
origStrWrp=new StringWrapper("Other String") // This only reassigns the copy of the reference and would give you the same problem
}
//Changes internal object
function (origStrWrp)
{
origStrWrp.myString = "Other String" // This doesn't change the reference, it changes the object that it refers to.
}
RussS
  • 16,476
  • 1
  • 34
  • 62
  • Why this is not happening with other objects? – glarkou Feb 07 '12 at 21:02
  • What makes you think that it isn't? – RussS Feb 07 '12 at 21:03
  • Because if I use a wrapper object its working. I can post some code if you want! – glarkou Feb 07 '12 at 21:04
  • I added a clarification to show you how the exact same thing is happening – RussS Feb 07 '12 at 21:12
  • `changeString(ms)` -- pass reference to `MainStr` instance. `MainStr` instance contains `str` which is a reference. `ms.str=" HERE"` -- change this reference to point to another String instance `System.out.println(ms.str)` -- take unchanged reference `ms` and then take what `str` points to, which was changed. – Suzan Cioc Feb 07 '12 at 21:18
4

In Java references are passed by value. Here is popular SO discussion to understand this topic. The reference str is scoped to changeString method only because of passing reference as value.

Community
  • 1
  • 1
kosa
  • 65,990
  • 13
  • 130
  • 167
  • Still worth having a read at the link above Salamis ;) it's interesting. You will find this link helpful http://javadude.com/articles/passbyvalue.htm?repost – MalsR Feb 07 '12 at 21:57
2

Strings are immutable in Java. In order for this to work you need to return the newly created string instance from the hangeString method.

static String changeString(String str)
{
    return " HERE";
}
0

Doing str=" HERE"; actually changes the object that str points to. It doesn't change the original object. If you want to modify the original, put it in a wrapper object.

Example:

public class MainStr {

    static class StringWrapper {
        public String str;
    }

    public static void main(String[] args) {
        StringWrapper foo = new StringWrapper();
        foo.str = "Hello!";
        System.out.println(foo.str);
        changeString(foo);
        System.out.println(foo.str);
    }

    static void changeString(StringWrapper str)
    {
        str.str = "Bye!";
    }
}
jli
  • 6,523
  • 2
  • 29
  • 37
  • @his Immutability has some benefits: http://stackoverflow.com/questions/3407403/whats-the-advantage-of-a-string-be-immutable – mtsz Feb 07 '12 at 20:58
  • @his By "modify" I meant set it to something else (i.e. change the object it points to, not the internal data) – jli Feb 07 '12 at 20:59
  • Sure, I am aware of that. I just wanted to point out that in this case you can't change the state of the object. – Hauke Ingmar Schmidt Feb 07 '12 at 21:00
0

Yes, Java is passing class arguments by reference. Impossible to tell it to do other way.

You can wrap your string into another class or use StringBuilder from the library.

P.S.

str=" HERE";

just replaces old reference to a new one pointing to " HERE". This does not touch old reference str outside a function.

P.P.S.

Probably my terminology is wrong. So, in plain words, Java variable of type String contains a reference to that string. This reference is passed into function. Assignment is changing a reference, not original object.

Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385
0

you are mixing things. although both variables are called 'str' they are in different 'scopes'

the first is only valid inside your main method while the second is only valid inside your changeString method.

it seems that if you want to accomplish your goal of using the changeString to make changes available within the main method; you will have to:

a) create a variable outside the methods - so that it will have a class (global) scope:

favorite share [g+] share [fb] share [tw]

I would like to ask a really simple question. I am just passing a String object to a function but the result is weird. I supposed that because I am passing an object(by reference) the result should have be " Here" and not "Hello". Why is this happening?

public class MainStr
{
String str = null;

public static void main(String[] args)
{
    str = "Hello!";
    System.out.println(str);
    changeString();  // there is no argument to supply
    System.out.println(str);


}

static void changeString()
{
    str= str + " HERE"; // variable is changed here
}

}

b) enable changeString to return a string, and use that:

public class MainStr 
{

/**
 * @param args
 */
public static void main(String[] args)
{
    String str = "Hello!";
    System.out.println(str);
    str = changeString(str);   // str has return value assigned to it!
    System.out.println(str);   // otherwise it would print out 'Hello!'


}

static String changeString(String str)
{
    str = str.concat(" HERE");
    return str;

}
}

NOTE: in the second option (b) you still two variable with different scopes and same name.

while in the first option (a) there is only one variable in the whole

hope this clarifies your doubts.

good luck!

Nicolas

Nicolas
  • 71
  • 1
  • 1