This is a classic trip-up for Java beginners. Part of the problem is that we lack a common language to identify this. Are parameters passed by value? Objects are passed by reference? Depending on who you are talking to there will be different reactions to the words pass by value and pass by reference, even though everyone wants to say the same thing.
The way to visualize this is to understand that java variable can be one of two things. It can either contain a primitive or a reference to an object. Think of that reference as an number pointing to a location in memory. It isn't a pointer in the C++ meaning in that it doesn't point to a specific memory location, it is more of a handle, in that it lets the JVM look up a specific memory location where the object can be found. But you can visualize it this way:
ArrayList<Integer> outer = @1234; //The first reference where the ArrayList was created.
You then call inner with the parameters of:
Puzzle.change(@1234);
Note that you do not pass the outer variable, you pass the value of @1234. outer cannot be changed in any way by being a parameter on a method. This is what we mean when we say pass by value. The value is passed, but it is disconnected from the outer variable.
Inside Puzzle:
public static void change(ArrayList<Integer> inner) { // a new reference inner is created.
//inner starts out as @1234
inner.add(7);
//now inner becomes @5678
inner = new ArrayList<Integer>();
//The object @5678 is changed.
inner.add(23);
//And printed.
System.out.println(inner);
}
But outer is still pointing to @1234 as the method could not change that, it never had the outer variable, it just had its contents. However, since the change method started out with a reference to @1234, the object at that location could indeed be changed by the method and the results visible to any other reference to @1234.
After the change method completes, nothing references the object @5678, so it becomes eligible for garbage collection.