0

I think this question is related to this question: Is Java "pass-by-reference" or "pass-by-value"?, but not really the same.

Suppose I have this loop code:

ArrayList<foo> list = new ArrayList<foo>();
Calendar cal = Calendar.getInstance();
for(int i = 0; i < 10; ++i) {
    cal.set(Calendar.HOUR, i);
    list.add(new foo(cal));
}
for(int i = 0; i < 10; ++i) {
    System.out.print(list.get(i).calToString());
}

foo.class:

public class foo {
    private Calendar mCal;
    public foo(Calendar cal) {
        mCal = cal;
    }
    public String calToString() {
        return String.valueOf(mCal.get(Calendar.HOUR));
    }
}

The resulting list has all its items Calendar.HOUR set to 9. It prints 9999999999. How can I make it so that each item will have 0-9 respectively? Will instantiating variable cal inside the loop be a performance issue (if in case foo is a more complex class)?

Community
  • 1
  • 1
Poly Bug
  • 1,514
  • 1
  • 14
  • 27
  • 1
    possible duplicate of [Is Java pass by value Or pass by reference Or both?](http://stackoverflow.com/questions/18249555/is-java-pass-by-value-or-pass-by-reference-or-both) – Ruchira Gayan Ranaweera Sep 10 '14 at 11:50

3 Answers3

3

Actually you are overwriting your object, you declared it outside the loop and you keep changing it's value.

You should create new instance inside the loop. No, you won't notice any performance issues.

Maroun
  • 94,125
  • 30
  • 188
  • 241
  • Okay, I instantiated the Calendar variable inside the loop, but still kept the declaration outside, then it gave list items with 0-9. But how is declaring the variable outside the loop different from declaring it inside the loop in terms of memory allocation? – Poly Bug Sep 10 '14 at 12:09
  • In terms of memory allocation, in the first case, you only allocated memory for one object and overwrote it on each iteration. In the second case (my answer), you create a new object each time. – Maroun Sep 10 '14 at 12:17
  • I meant the declaration. I did what you said and instantiated inside the loop, but I kept the declaration outside. What is the difference if I also moved the declaration inside the loop? – Poly Bug Sep 10 '14 at 12:23
  • 1
    It's not different, the compiler will optimize that. The bytecode will be the same. – Maroun Sep 10 '14 at 12:24
  • But please note that it's clearer to declare it outside the loop. – Maroun Sep 10 '14 at 12:30
2

You would need to initialize a new Calendar for each iteration of your loop.

Something like:

for(int i = 0; i < 10; ++i) {
    Calendar cal = Calendar.getInstance();

Otherwise, the same instance is referenced everytime.

Therefore, the set invocation modifies the same Calendar, which is why you are getting all 9s.

More elegantly perhaps, you could initialize your Foo class with a constructor taking the actual hour int.

Then you would change Foo to have its own Calendar instance.

Mena
  • 47,782
  • 11
  • 87
  • 106
0

class Main

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

    ArrayList<foo> list = new ArrayList<foo>();
    Calendar cal = null;
    for (int i = 0; i < 10; ++i) {
        cal=Calendar.getInstance();
        cal.set(Calendar.HOUR, i);
        list.add(new foo(cal));
    }
    for (int i = 0; i < 10; ++i) {
        System.out.print(list.get(i).calToString());
    }
}

}

class foo { private Calendar mCal;

public foo(Calendar cal) {
    mCal = cal;
}

public String calToString() {
    return String.valueOf(mCal.get(Calendar.HOUR));
}

}

you are overwriting your calender object

Amit Kumar
  • 547
  • 3
  • 10