Java is pass by value, but the value passed is the reference to the object in memory. Specifically l1
points to a list, when you call a method, the variable l1
isn't passed (that would be pass by reference), but the value of l1
is passed, this value is a reference to the same object. If you reassign the argument l
with a different List
, then the variable in the caller (l1
) is unchanged.
Specifically in your example this is further compounded by the fact that List.subList
is a view on the underlying list. Modifying the sublist (in your code calling clear()
) will also modify the backing original list.
Your specific example is even included in the API documentation:
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.
This method eliminates the need for explicit range operations (of the sort that commonly exist for arrays). Any operation that expects a list can be used as a range operation by passing a subList view instead of a whole list. For example, the following idiom removes a range of elements from a list:
list.subList(from, to).clear();