There are already great answers that cover this. I wanted to make a small contribution by sharing a very simple example (which will compile) contrasting the behaviors between Pass-by-reference in c++ and Pass-by-value in Java.
A few points:
- The term "reference" is a overloaded with two separate meanings. In Java it simply means a pointer, but in the context of "Pass-by-reference" it means a handle to the original variable which was passed in.
- Java is Pass-by-value. Java is a descendent of C (among other languages). Before C, several (but not all) earlier languages like FORTRAN and COBOL supported PBR, but C did not. PBR allowed these other languages to make changes to the passed variables inside sub-routines. In order to accomplish the same thing (i.e. change the values of variables inside functions), C programmers passed pointers to variables into functions. Languages inspired by C, such as Java, borrowed this idea and continue to pass pointer to methods as C did, except that Java calls its pointers References. Again, this is a different use of the word "Reference" than in "Pass-By-Reference".
- C++ allows Pass-by-reference by declaring a reference parameter using the "&" character (which happens to be the same character used to indicate "the address of a variable" in both C and C++). For example, if we pass in a pointer by reference, the parameter and the argument are not just pointing to the same object. Rather, they are the same variable. If one gets set to a different address or to null, so does the other.
- In the C++ example below I'm passing a pointer to a null terminated string by reference. And in the Java example below I'm passing a Java reference to a String (again, the same as a pointer to a String) by value. Notice the output in the comments.
C++ pass by reference example:
using namespace std;
#include <iostream>
void change (char *&str){ // the '&' makes this a reference parameter
str = NULL;
}
int main()
{
char *str = "not Null";
change(str);
cout<<"str is " << str; // ==>str is <null>
}
Java pass "a Java reference" by value example
public class ValueDemo{
public void change (String str){
str = null;
}
public static void main(String []args){
ValueDemo vd = new ValueDemo();
String str = "not null";
vd.change(str);
System.out.println("str is " + str); // ==> str is not null!!
// Note that if "str" was
// passed-by-reference, it
// WOULD BE NULL after the
// call to change().
}
}
EDIT
Several people have written comments which seem to indicate that either they are not looking at my examples or they don't get the c++ example. Not sure where the disconnect is, but guessing the c++ example is not clear. I'm posting the same example in pascal because I think pass-by-reference looks cleaner in pascal, but I could be wrong. I might just be confusing people more; I hope not.
In pascal, parameters passed-by-reference are called "var parameters". In the procedure setToNil below, please note the keyword 'var' which precedes the parameter 'ptr'. When a pointer is passed to this procedure, it will be passed by reference. Note the behavior: when this procedure sets ptr to nil (that's pascal speak for NULL), it will set the argument to nil--you can't do that in Java.
program passByRefDemo;
type
iptr = ^integer;
var
ptr: iptr;
procedure setToNil(var ptr : iptr);
begin
ptr := nil;
end;
begin
new(ptr);
ptr^ := 10;
setToNil(ptr);
if (ptr = nil) then
writeln('ptr seems to be nil'); { ptr should be nil, so this line will run. }
end.
EDIT 2
Some excerpts from "THE Java Programming Language" by Ken Arnold, James Gosling (the guy who invented Java), and David Holmes, chapter 2, section 2.6.5
All parameters to methods are passed "by value". In other words,
values of parameter variables in a method are copies of the invoker
specified as arguments.
He goes on to make the same point regarding objects . . .
You should note that when the parameter is an object reference, it is
the object reference-not the object itself-that is passed "by value".
And towards the end of the same section he makes a broader statement about java being only pass by value and never pass by reference.
The Java programming language does not pass objects by reference; it
passes object references by value. Because two copies of the same
reference refer to the same actual object, changes made through one
reference variable are visible through the other. There is exactly one
parameter passing mode-pass by value-and that helps keep things
simple.
This section of the book has a great explanation of parameter passing in Java and of the distinction between pass-by-reference and pass-by-value and it's by the creator of Java. I would encourage anyone to read it, especially if you're still not convinced.
I think the difference between the two models is very subtle and unless you've done programming where you actually used pass-by-reference, it's easy to miss where two models differ.
I hope this settles the debate, but probably won't.
EDIT 3
I might be a little obsessed with this post. Probably because I feel that the makers of Java inadvertently spread misinformation. If instead of using the word "reference" for pointers they had used something else, say
dingleberry, there would've been no problem. You could say, "Java passes dingleberries by value and not by reference", and nobody would be confused.
That's the reason only Java developers have issue with this. They look at the word "reference" and think they know exactly what that means, so they don't even bother to consider the opposing argument.
Anyway, I noticed a comment in an older post, which made a balloon analogy which I really liked. So much so that I decided to glue together some clip-art to make a set of cartoons to illustrate the point.
Passing a reference by value--Changes to the reference are not reflected in the caller's scope, but the changes to the object are. This is because the reference is copied, but the both the original and the copy refer to the same object.
Pass by reference--There is no copy of the reference. Single reference is shared by both the caller and the function being called. Any changes to the reference or the Object's data are reflected in the caller's scope.
EDIT 4
I have seen posts on this topic which describe the low level implementation of parameter passing in Java, which I think is great and very helpful because it makes an abstract idea concrete. However, to me the question is more about the behavior described in the language specification than about the technical implementation of the behavior. This is an exerpt from the Java Language Specification, section 8.4.1 :
When the method or constructor is invoked (§15.12), the values of the
actual argument expressions initialize newly created parameter
variables, each of the declared type, before execution of the body of
the method or constructor. The Identifier that appears in the
DeclaratorId may be used as a simple name in the body of the method or
constructor to refer to the formal parameter.
Which means, java creates a copy of the passed parameters before executing a method. Like most people who studied compilers in college, I used "The Dragon Book" which is THE compilers book. It has a good description of "Call-by-value" and "Call-by-Reference" in Chapter 1. The Call-by-value description matches up with Java Specs exactly.
Back when I studied compilers-in the 90's, I used the first edition of the book from 1986 which pre-dated Java by about 9 or 10 years. However, I just ran across a copy of the 2nd Eddition from 2007 which actually mentions Java! Section 1.6.6 labeled "Parameter Passing Mechanisms" describes parameter passing pretty nicely. Here is an excerpt under the heading "Call-by-value" which mentions Java:
In call-by-value, the actual parameter is evaluated (if it is an
expression) or copied (if it is a variable). The value is placed in
the location belonging to the corresponding formal parameter of the
called procedure. This method is used in C and Java, and is a common
option in C++ , as well as in most other languages.
C++
and start to be confused when touchingJava
, this might help as shortcut. – jack