for example:
public static void main(String[] args)throws InterruptedException {
List<String> l1 = new LinkedList<String>();
String[] s1 = {"aa","bb","cc","dd"};
for(String k : s1)
l1.add(k);
removeStuff(l1,1,2);
printList(l1);
}
private static void printList(List<String> l) {
for(String b : l){
System.out.print(b + ' ');
}
private static void removeStuff(List<String> l, int i, int j) {
l.subList(1, 3).clear();
}
it will print aa dd instead of aa bb cc dd. So I am just wondering that, since java is "pass-by-value", how could the linkedlist l1 be changed by the method removeStuff?
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();
Java has a lot of history and the pass by value
law wasn't the best idea. The problem is that an object reference is considered a value
. So technically, yes, you are passing values around. However, these values reference points in memory, and those memory addresses can be modified by other methods.
When you pass the list to a method, the value you are passing is actually a reference to the list in memory.
Java is pass by value, but when you pass an object into a method, it is passing a copy of the reference to that object.
Think of every reference as a "pointer" to an object. The outer method has a reference to the list and the method you call gets a reference to it, too. They both have their own "pointer" that points to the same place.
If one of the methods modifies the object, they are modifying what the reference points to. Since both of their references are pointing to the same place, that means they both see the effect.
Java uses pass by reference for an object, but the reference is the alias to the same memory location not the original variable. That is why some people who do not get it say that Java uses always pass by value, which is half true. So the alias is pointing to the same memory as original variable but it is not the original variable. As long as you don't change the alias memory address you can manipulate the elements of the LIST the same way as using the original variable. I hope it is clear enough to understand.