0

In below code, I assumed both objects have references to the very same object but below example says I am wrong. Sorry if it is a duplicate.

    class A {
        public String a;
        public void set(String a) {
            this.a = a;
        }
    }

    class B {
        public String b;
        public void set(String b) {
            this.b = b;
        }
    }

    A aC = new A();
    B bC = new B();

    String str = "aaa";

    aC.set(str);
    bC.set(aC.a);

    aC.a += "a";

    System.out.println(aC.a);
    System.out.println(bC.b);
bfaskiplar
  • 865
  • 1
  • 7
  • 23
  • 3
    Java is pass by **value**. *Always*. – Hovercraft Full Of Eels Mar 09 '13 at 17:47
  • @HovercraftFullOfEels: But all non basic types are references. So you are passing a reference by value. – Martin York Mar 09 '13 at 19:17
  • @LokiAstari: correct, you are passing a reference by value or a primitive by value.. – Hovercraft Full Of Eels Mar 09 '13 at 20:48
  • @HovercraftFullOfEels: So the OP assumptions were correct. He was just not taking into account the immutability of strings (thus += returns a new object) and thus your original comment is not helpful. – Martin York Mar 09 '13 at 23:01
  • @LokiAstari: Mutability has nothing to do with it. `+=` is always just shorthand for `=` and `+`. And assignment of references always means the same thing, regardless of what objects the references may point to and whether they may be mutable or not. – newacct Mar 10 '13 at 07:07

5 Answers5

3

Java is pass by value. References are passed by value.

aC.a += "a" creates a new String object, which is why it's not reflected in bC.

Literally, you're saying

aC.a = aC.a + "a"

So you can interpret that = sign to mean aC.a maps to a new String object which is the concatenation of aC.a and "a". But while you change the reference of aC.a you are not changing the reference of bC.b, so it will point to the same old String.

ktm5124
  • 11,861
  • 21
  • 74
  • 119
3

What confuses you is that you think

aC.a += "a";

modifies the state of the String object referenced by aC.a. That's not the case. Strings are immutable, and the above line of code creates a new String object and assigns it to aC.a, leaving all the other references to the original object as is.

Make the same test with a StringBuilder, and call

aC.a.append("a");

and you'll get a different result.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • For the original piece of code that I am working on I wanted two distinct objects to have same variable which is of type enum and when I want to change enum I want both of variables to change. I assume enums are immutable, too. So what could be the solution in this case? – bfaskiplar Mar 09 '13 at 17:51
  • Then my guess was wrong, and you actually think Java passes by reference. This is not the case. References are passed by value. To solve your problem, make the two objects (A and B) share a single other object (C), which itself references an enum value (E). Change the enum reference in C (c.e = newEnumValue), and A and B, still sharing the same C, will see the new enum value. – JB Nizet Mar 09 '13 at 17:54
  • Ok, in this case that class which C object is type of should be the wrapper class. In fact, I wonder if there is another solution without a wrapper – bfaskiplar Mar 09 '13 at 18:04
  • I don't see any other solution. – JB Nizet Mar 09 '13 at 18:05
3

The Java Spec says that everything in Java is pass-by-value. There is no such thing as "pass-by-reference" in Java.

The key to understanding this is that something like

Dog myDog;

is not a Dog; it's actually a pointer to a Dog.

What that means, is when you have

Dog myDog = new Dog("Rover");
foo(myDog);

you're essentially passing the address of the created Dog object to the foo method.

(I say essentially b/c Java pointers aren't direct addresses, but it's easiest to think of them that way)

Suppose the Dog object resides at memory address 42. This means we pass 42 to the method.

if the Method were defined as

public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC
}

let's look at what's happening.

  • the parameter someDog is set to the value 42
  • at line "AAA"
    • someDog is followed to the Dog it points to (the Dog object at address 42)
    • that Dog (the one at address 42) is asked to change his name to Max
  • at line "BBB"
    • a new Dog is created. Let's say he's at address 74
    • we assign the parameter someDog to 74
  • at line "CCC"
    • someDog is followed to the Dog it points to (the Dog object at address 74)
    • that Dog (the one at address 74) is asked to change his name to Rowlf
  • then, we return

Now let's think about what happens outside the method:

Did myDog change?

There's the key.

Keeping in mind that myDog is a pointer, and not an actual Dog, the answer is NO. myDog still has the value 42; it's still pointing to the original Dog.

It's perfectly valid to follow an address and change what's at the end of it; that does not change the variable, however.

Java works exactly like C. You can assign a pointer, pass the pointer to a method, follow the pointer in the method and change the data that was pointed to. However, you cannot change where that pointer points.

Jorge Martins
  • 321
  • 2
  • 10
1

There are three string objects in the JVM. "aaa", "a" and "aaaa" (Since strings are immutable). Initially aC.a and bC.b were pointing to the same string object "aaa". In this line aC.a += "a"; code is changing reference of aC.a to point to "aaaa". So now aC.a -> "aaaa" and bC.b -> "aaa". I hope I am clear.

ankitkpd
  • 663
  • 5
  • 19
0

Java is actually pass-by-value-of-reference. The actual reference is copied and that copy is sent to the function.

Daedalus
  • 1,667
  • 10
  • 12
  • Nevertheless, don't both of the references point to very same object in above example? – bfaskiplar Mar 09 '13 at 17:47
  • They do until your += operation creates a new string at the original reference, making the two references now pointing at different string objects. – Daedalus Mar 09 '13 at 17:50