Wednesday, 8 June 2016

Are arrays passed by value or passed by reference in Java?











Arrays are not a primitive type in Java, but they are not objects either, so are they passed by value or by reference? Does it depend on what the array contains, for example references or a primitive type?


Answer



Your question is based on a false premise.




Arrays are not a primitive type in Java, but they are not objects either ... "





In fact, all arrays in Java are objects1. Every Java array type has java.lang.Object as its supertype, and inherits the implementation of all methods in the Object API.




... so are they passed by value or by reference? Does it depend on what the array contains, for example references or a primitive type?




Short answers: 1) pass by value, and 2) it makes no difference.




Longer answer:



Like all Java objects, arrays are passed by value ... but the value is the reference to the array. So, when you assign something to a cell of the array in the called method, you will be assigning to the same array object that the caller sees.



This is NOT pass-by-reference. Real pass-by-reference involves passing the address of a variable. With real pass-by-reference, the called method can assign to its local variable, and this causes the variable in the caller to be updated.



But not in Java. In Java, the called method can update the contents of the array, and it can update its copy of the array reference, but it can't update the variable in the caller that holds the caller's array reference. Hence ... what Java is providing is NOT pass-by-reference.



Here are some links that explain the difference between pass-by-reference and pass-by-value. If you don't understand my explanations above, or if you feel inclined to disagree with the terminology, you should read them.






Related SO question:





Historical background:



The phrase "pass-by-reference" was originally "call-by-reference", and it was used to distinguish the argument passing semantics of FORTRAN (call-by-reference) from those of ALGOL-60 (call-by-value and call-by-name).





  • In call-by-value, the argument expression is evaluated to a value, and that value is copied to the called method.


  • In call-by-reference, the argument expression is partially evaluated to an "lvalue" (i.e. the address of a variable or array element) that is passed to the calling method. The calling method can then directly read and update the variable / element.


  • In call-by-name, the actual argument expression is passed to the calling method (!!) which can evaluate it multiple times (!!!). This was complicated to implement, and could be used (abused) to write code that was very difficult to understand. Call-by-name was only ever used in Algol-60 (thankfully!).




UPDATE



Actually, Algol-60's call-by-name is similar to passing lambda expressions as parameters. The wrinkle is that these not-exactly-lambda-expressions (they were referred to as "thunks" at the implementation level) can indirectly modify the state of variables that are in scope in the calling procedure / function. That is part of what made them so hard to understand. (See the Wikipedia page on Jensen's Device for example.)







1. Nothing in the linked Q&A (Arrays in Java and how they are stored in memory) either states or implies that arrays are not objects.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...