0

I didn't expect that new doesn't change the instance variables if instance variables are already assigned.

Did I understand correctly?

class Foo {
    String name = "Java";
}
class Main {
    public static void main(String args[]) {
        Foo foos[] = { new Foo(), new Foo() };
        foos[0].name = "bar";
        for (Foo c : foos) c = new Foo();
        for (Foo c : foos) System.out.println(c.name);
        for (Foo c : foos) c.name = "baz";
        for (Foo c : foos) System.out.println(c.name);
    }
}

Output

bar
Java
baz
baz

In the above example, the new works more like casting the object to the same class is already it. What is the practical use for this behavior?

Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424
  • 2
    The `new` operator is just doing its job, which is to create new objects. I see nothing here which requires explanation. – Tim Biegeleisen Jan 16 '17 at 09:01
  • 1
    It's really not clear what you mean here...You've got 3 uses of `new` - which of those is what you're surprised by? And what does this have to do with locales? What do you *expect* the result to be? Are you surprised that `c = new Foo();` doesn't actually change the value in the collection? If so, that's got *nothing* to do with `new`. – Jon Skeet Jan 16 '17 at 09:01
  • There are four independent variables `c`. There is no reassignment except in the first loop. But this has no effect on the array. – Albjenow Jan 16 '17 at 09:02
  • 2
    You're changing `c`, not `Foo[0]` or `Foo[1]`. – Kerrek SB Jan 16 '17 at 09:09
  • Possible duplicate of [Is Java "pass-by-reference" or "pass-by-value"?](http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value) – Alex K Jan 16 '17 at 09:32

1 Answers1

3

It is because Java is always pass-by-value. Variable c doesn't reflect the array element, but its reference value is copied. So at first, c points to the value of the array element, but when you reassign c using c = new Foo(), variable c will point to something else. For that reason, the array element itself is unaffected.

  1. In this code,

    for (Foo c : foos)
    

    the reference to the array element (for example foos[0]) is copied to c.

  2. But when you assign a new Foo instance to c, it is not reflected by the array, you simply have assigned something to c.

    c = new Foo();
    
  3. In the next loop iteration, the next element is reassigned to c, leaving the object you created by c = new Foo() loosely into memory. It will be garbage collected soon.

I noticed that you're coming from a C world, which explains the confusion. But in Java, arguments passed to a method or the element reference in a foreach loop are always copied. This post explains further details about this behavior.

Community
  • 1
  • 1
MC Emperor
  • 22,334
  • 15
  • 80
  • 130