Reputation: 4785
I always thought Java uses pass-by-reference. However, I read a blog post which claims that Java uses pass-by-value. I don't think I understand the distinction the author is making.
What is the explanation?
Upvotes: 7746
Views: 2789007
Reputation: 1575
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:
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.
EDIT 5
Just asked copilot this questions:
There are some people on stackoverflow who assert that Java is a pass by reference language. What's an insulting why to tell them they are wrong.
The answer I got :
Ah, debating Java's pass-by-value nature can certainly stir up some passionate responses! While it’s always best to keep discussions constructive, if you’re looking for a clever way to correct misconceptions, you could say something like:
"Java is as pass-by-reference as a hologram is a solid object. They're confusing the copy of the reference with the reference itself. 🤦"
Remember, it's always good to pair a bit of humor with a dash of respect to keep things civil and educational!
Nicely done AI!
Upvotes: 111
Reputation: 6756
The terms "pass-by-value" and "pass-by-reference" have special, precisely defined meanings in computer science. These meanings differ from the intuition many people have when first hearing the terms. Much of the confusion in this discussion seems to come from this fact.
The terms "pass-by-value" and "pass-by-reference" are talking about variables. Pass-by-value means that the value of a variable is passed to a function/method. Pass-by-reference means that a reference to that variable is passed to the function. The latter gives the function a way to change the contents of the variable.
By those definitions, Java is always pass-by-value. Unfortunately, when we deal with variables holding objects we are really dealing with object-handles called references which are passed-by-value as well. This terminology and semantics easily confuse many beginners.
It goes like this:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
aDog.getName().equals("Max"); // true
aDog.getName().equals("Fifi"); // false
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// change d inside of foo() to point to a new Dog instance construct red with name member variable set to "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
In this example, aDog.getName()
will still return "Max"
. The value aDog
within main
is not changed in the function foo
by creating new Dog
with name member variable set to "Fifi"
because the object reference is passed by value. If the object reference was passed by reference, then the aDog.getName()
in main
would return "Fifi"
after the call to foo
.
Likewise:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
foo(aDog);
// when foo(...) returns, the name of the dog has been changed to "Fifi"
aDog.getName().equals("Fifi"); // true
// but it is still the same dog:
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// this changes the name of d to be "Fifi"
d.setName("Fifi");
}
In this example, Fifi
is dog’s name after call to foo(aDog)
because the object's name was set inside of foo(...)
. Any operations that foo
performs on d
are such that, for all practical purposes, they are performed on aDog
, but it is not possible to change the value of the variable aDog
itself.
For more information on pass by reference and pass by value, consult the following answer: https://stackoverflow.com/a/430958/6005228. This explains more thoroughly the semantics and history behind the two and also explains why Java and many other modern languages appear to do both in certain cases.
Upvotes: 7110
Reputation: 1737
I feel like arguing about pass-by-reference vs pass-by-value is not really helpful.
If you say that Java is pass-by-whatever, you are not providing a complete answer. Here is some additional information that will hopefully help you understand what actually happens in memory.
Crash course on stack/heap before we get to the Java implementation: Values go on and off the stack in a nice orderly fashion, like a stack of plates at a cafeteria. Memory in the heap (also known as dynamic memory) is haphazard and disorganized. The JVM just finds space wherever it can, and frees it up as the variables that use it are no longer needed.
Okay. First off, local primitives go on the stack. So this code:
int x = 3;
float y = 101.1f;
boolean amIAwesome = true;
results in this:
When you declare and instantiate an object. The actual object goes on the heap. What goes on the stack? The address of the object on the heap. C++ programmers would call this a pointer, but some Java developers are against the word "pointer". Whatever. Just know that the address of the object goes on the stack.
Like so:
int problems = 99;
String name = "Jay-Z";
An array is an object, so it goes on the heap as well. And what about the objects in the array? They get their own heap space, and the address of each object goes inside the array.
JButton[] marxBros = new JButton[3];
marxBros[0] = new JButton("Groucho");
marxBros[1] = new JButton("Zeppo");
marxBros[2] = new JButton("Harpo");
So, what gets passed in when you call a method? If you pass in an object, what you're actually passing in is the address of the object. Some might say the "value" of the address, and some say it's just a reference to the object. This is the genesis of the holy war between "reference" and "value" proponents. What you call it isn't as important as that you understand that what's getting passed in is the address to the object.
private static void shout(String name){
System.out.println("There goes " + name + "!");
}
public static void main(String[] args){
String hisName = "John J. Jingleheimerschmitz";
String myName = hisName;
shout(myName);
}
One String gets created and space for it is allocated in the heap, and the address to the string is stored on the stack and given the identifier hisName
, since the address of the second String is the same as the first, no new String is created and no new heap space is allocated, but a new identifier is created on the stack. Then we call shout()
: a new stack frame is created and a new identifier, name
is created and assigned the address of the already-existing String.
So, value, reference? You say "potato".
Upvotes: 302
Reputation: 159
Java is a pass by value(stack memory)
How it works
Let's first understand that where java stores primitive data type and object data type.
Primitive data types itself and object references are stored in the stack. Objects themselves are stored in the heap.
It means, Stack memory stores primitive data types and also the addresses of objects.
And you always pass a copy of the bits of the value of the reference.
If it's a primitive data type then these copied bits contain the value of the primitive data type itself, That's why when we change the value of argument inside the method then it does not reflect the changes outside.
If it's an object data type like Foo foo=new Foo() then in this case copy of the address of the object passes like file shortcut , suppose we have a text file abc.txt at C:\desktop and suppose we make shortcut of the same file and put this inside C:\desktop\abc-shortcut so when you access the file from C:\desktop\abc.txt and write 'Stack Overflow' and close the file and again you open the file from shortcut then you write ' is the largest online community for programmers to learn' then total file change will be 'Stack Overflow is the largest online community for programmers to learn' which means it doesn't matter from where you open the file , each time we were accessing the same file , here we can assume Foo as a file and suppose foo stored at 123hd7h(original address like C:\desktop\abc.txt ) address and 234jdid(copied address like C:\desktop\abc-shortcut which actually contains the original address of the file inside) .. So for better understanding make shortcut file and feel..
Upvotes: 90
Reputation: 924
Java is always pass by value, not pass by reference
First of all, we need to understand what pass by value and pass by reference are.
Pass by value means that you are making a copy in memory of the actual parameter's value that is passed in. This is a copy of the contents of the actual parameter.
Pass by reference (also called pass by address) means that a copy of the address of the actual parameter is stored.
Sometimes Java can give the illusion of pass by reference. Let's see how it works by using the example below:
public class PassByValue {
public static void main(String[] args) {
Test t = new Test();
t.name = "initialvalue";
new PassByValue().changeValue(t);
System.out.println(t.name);
}
public void changeValue(Test f) {
f.name = "changevalue";
}
}
class Test {
String name;
}
The output of this program is:
changevalue
Let's understand step by step:
Test t = new Test();
As we all know it will create an object in the heap and return the reference value back to t. For example, suppose the value of t is 0x100234
(we don't know the actual JVM internal value, this is just an example) .
new PassByValue().changeValue(t);
When passing reference t to the function it will not directly pass the actual reference value of object test, but it will create a copy of t and then pass it to the function. Since it is passing by value, it passes a copy of the variable rather than the actual reference of it. Since we said the value of t was 0x100234
, both t and f will have the same value and hence they will point to the same object.
If you change anything in the function using reference f it will modify the existing contents of the object. That is why we got the output changevalue
, which is updated in the function.
To understand this more clearly, consider the following example:
public class PassByValue {
public static void main(String[] args) {
Test t = new Test();
t.name = "initialvalue";
new PassByValue().changeRefence(t);
System.out.println(t.name);
}
public void changeRefence(Test f) {
f = null;
}
}
class Test {
String name;
}
Will this throw a NullPointerException
? No, because it only passes a copy of the reference.
In the case of passing by reference, it could have thrown a NullPointerException
, as seen below:
Upvotes: 102
Reputation: 117665
Java always passes arguments by value, NOT by reference.
Let me explain this through an example:
public class Main {
public static void main(String[] args) {
Foo f = new Foo("f");
changeReference(f); // It won't change the reference!
modifyReference(f); // It will modify the object that the reference variable "f" refers to!
}
public static void changeReference(Foo a) {
Foo b = new Foo("b");
a = b;
}
public static void modifyReference(Foo c) {
c.setAttribute("c");
}
}
I will explain this in steps:
Declaring a reference named f
of type Foo
and assign it a new object of type Foo
with an attribute "f"
.
Foo f = new Foo("f");
From the method side, a reference of type Foo
with a name a
is declared and it's initially assigned null
.
public static void changeReference(Foo a)
As you call the method changeReference
, the reference a
will be assigned the object which is passed as an argument.
changeReference(f);
Declaring a reference named b
of type Foo
and assign it a new object of type Foo
with an attribute "b"
.
Foo b = new Foo("b");
a = b
makes a new assignment to the reference a
, not f
, of the object whose attribute is "b"
.
As you call modifyReference(Foo c)
method, a reference c
is created and assigned the object with attribute "f"
.
c.setAttribute("c");
will change the attribute of the object that reference c
points to it, and it's the same object that reference f
points to it.
Upvotes: 2133
Reputation: 481
Java is always pass by value, not pass by reference
First of all, we need to understand what pass by value and pass by reference are.
Pass by value means that you are making a copy in memory of the actual parameter's value that is passed in. This is a copy of the contents of the actual parameter.
Pass by reference (also called pass by address) means that a copy of the address of the actual parameter is stored.
Sometimes Java can give the illusion of pass by reference. Let's see how it works by using the example below:
public class PassByValue {
public static void main(String[] args) {
Test t = new Test();
t.name = "initialvalue";
new PassByValue().changeValue(t);
System.out.println(t.name);
}
public void changeValue(Test f) {
f.name = "changevalue";
}
}
class Test {
String name;
}
The output of this program is:
changevalue
Let's understand step by step:
Test t = new Test();
As we all know it will create an object in the heap and return the reference value back to t. For example, suppose the value of t is 0x100234 (we don't know the actual JVM internal value, this is just an example) .
first illustration
new PassByValue().changeValue(t);
When passing reference t to the function it will not directly pass the actual reference value of object test, but it will create a copy of t and then pass it to the function. Since it is passing by value, it passes a copy of the variable rather than the actual reference of it. Since we said the value of t was 0x100234, both t and f will have the same value and hence they will point to the same object.
second illustration
If you change anything in the function using reference f it will modify the existing contents of the object. That is why we got the output changevalue, which is updated in the function.
To understand this more clearly, consider the following example:
public class PassByValue {
public static void main(String[] args) {
Test t = new Test();
t.name = "initialvalue";
new PassByValue().changeRefence(t);
System.out.println(t.name);
}
public void changeRefence(Test f) {
f = null;
}
}
class Test {
String name;
}
Will this throw a NullPointerException? No, because it only passes a copy of the reference. In the case of passing by reference, it could have thrown a NullPointerException, as seen below:
third illustration
Hopefully this will help.
Upvotes: 10
Reputation: 4855
There are two cases of interest:
For a variable of primitive type (eg. int
, boolean
, char
, and others...), when you use the variable name in a function argument, you are passing by value. This value (eg. 5
, true
, or 'c'
) is "copied", and the variable retains its original value after the method invocation, because there are now two copies of the data in existance. One is outside of the function call, the other is inside.
For a variable of reference type (eg. String
, Object
, etc...), when you use the variable name for a function argument, you are passing the reference value contained in the variable. The reference value is copied, just as in the first example above, and the variable external to the function also retains its value the method invocation. The reference is still to the same object. What differs in this case is that the function may alter data inside the object which is referenced.
Either way, you're always passing stuff by value.
Upvotes: 22
Reputation: 17268
There are already many answers to this question, and many of them are misleading.
There are two simple statements which explain how Java behaves in all cases:
What does this mean?
int
, you literally are holding a value. A variable when initialized to an int value "contains" that value directly. If you pass it to a function, a copy of the value is made in the variable which holds the argument to the function. This variable is called a "parameter". Hence Java is a pass-by-Value language.Object
) holds an indirect reference to a structure of data containing the Objects data. The variable is a label, rather than holding the value directly, it contains a label which is used to reference or lookup an objects data.Note I am not describing implementation details above. The implementation details could be anything. I am simply describing the behaviour of the language.
Some further explanation as to why I think other answers are confusing or misleading.
Therefore to even mention pointers is wrong. The implementation details of the JVM might use data which is akin to virtual memory addresses, but this is totally hidden from the user of the Java language. That is the point of programming languages, to abstract the programmer away from hardware details. With languages like C and C++, pointers are a key focus of the language because it was designed for systems engineering where detailed control over memory is required.
Upvotes: -2
Reputation: 74641
Data is shared between functions by passing parameters. Now, there are 2 ways of passing parameters:
passed by reference : caller and callee use same variable for parameter.
passed by value : caller and callee have two independent variables with same value.
Java uses pass by value
Java follows the following rules in storing variables:
Example using primitive data type:
public class PassByValuePrimitive {
public static void main(String[] args) {
int i=5;
System.out.println(i); //prints 5
change(i);
System.out.println(i); //prints 5
}
private static void change(int i) {
System.out.println(i); //prints 5
i=10;
System.out.println(i); //prints 10
}
}
Example using object:
public class PassByValueObject {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("prem");
list.add("raj");
new PassByValueObject().change(list);
System.out.println(list); // prints [prem, raj, ram]
}
private void change(List list) {
System.out.println(list.get(0)); // prem
list.add("ram");
list=null;
System.out.println(list.add("bheem")); //gets NullPointerException
}
}
Upvotes: 16
Reputation: 30652
I just noticed you referenced my article.
The Java Spec says that everything in Java is pass-by-value. There is no such thing as "pass-by-reference" in Java.
The key to understanding this is that something like
Dog myDog;
is not a Dog; it's actually a pointer to a Dog. The use of the term "reference" in Java is very misleading and is what causes most of the confusion here. What they call "references" act/feel more like what we'd call "pointers" in most other languages.
What that means, is when you have
Dog myDog = new Dog("Rover");
foo(myDog);
you're essentially passing the address of the created Dog
object to the foo
method.
(I say essentially because Java pointers/references aren't direct addresses, but it's easiest to think of them that way.)
Suppose the Dog
object resides at memory address 42. This means we pass 42 to the method.
if the Method were defined as
public void foo(Dog someDog) {
someDog.setName("Max"); // AAA
someDog = new Dog("Fifi"); // BBB
someDog.setName("Rowlf"); // CCC
}
let's look at what's happening.
someDog
is set to the value 42someDog
is followed to the Dog
it points to (the Dog
object at address 42)Dog
(the one at address 42) is asked to change his name to MaxDog
is created. Let's say he's at address 74someDog
to 74Dog
it points to (the Dog
object at address 74)Dog
(the one at address 74) is asked to change his name to RowlfNow let's think about what happens outside the method:
Did myDog
change?
There's the key.
Keeping in mind that myDog
is a pointer, and not an actual Dog
, the answer is NO. myDog
still has the value 42; it's still pointing to the original Dog
(but note that because of line "AAA", its name is now "Max" - still the same Dog; myDog
's value has not changed.)
It's perfectly valid to follow an address and change what's at the end of it; that does not change the variable, however.
Java works exactly like C. You can assign a pointer, pass the pointer to a method, follow the pointer in the method and change the data that was pointed to. However, the caller will not see any changes you make to where that pointer points. (In a language with pass-by-reference semantics, the method function can change the pointer and the caller will see that change.)
In C++, Ada, Pascal and other languages that support pass-by-reference, you can actually change the variable that was passed.
If Java had pass-by-reference semantics, the foo
method we defined above would have changed where myDog
was pointing when it assigned someDog
on line BBB.
Think of reference parameters as being aliases for the variable passed in. When that alias is assigned, so is the variable that was passed in.
A discussion in the comments warrants some clarification...
In C, you can write
void swap(int *x, int *y) {
int t = *x;
*x = *y;
*y = t;
}
int x = 1;
int y = 2;
swap(&x, &y);
This is not a special case in C. Both languages use pass-by-value semantics. Here the call site is creating additional data structure to assist the function to access and manipulate data.
The function is being passed pointers to data, and follows those pointers to access and modify that data.
A similar approach in Java, where the caller sets up assisting structure, might be:
void swap(int[] x, int[] y) {
int temp = x[0];
x[0] = y[0];
y[0] = temp;
}
int[] x = {1};
int[] y = {2};
swap(x, y);
(or if you wanted both examples to demonstrate features the other language doesn't have, create a mutable IntWrapper class to use in place of the arrays)
In these cases, both C and Java are simulating pass-by-reference. They're still both passing values (pointers to ints or arrays), and following those pointers inside the called function to manipulate the data.
Pass-by-reference is all about the function declaration/definition, and how it handles its parameters. Reference semantics apply to every call to that function, and the call site only needs to pass variables, no additional data structure.
These simulations require the call site and the function to cooperate. No doubt it's useful, but it's still pass-by-value.
Upvotes: 3615
Reputation: 71999
Basically, reassigning Object parameters doesn't affect the argument, e.g.,
private static void foo(Object bar) {
bar = null;
}
public static void main(String[] args) {
String baz = "Hah!";
foo(baz);
System.out.println(baz);
}
will print out "Hah!"
instead of null
. The reason this works is because bar
is a copy of the value of baz
, which is just a reference to "Hah!"
. If it were the actual reference itself, then foo
would have redefined baz
to null
.
Upvotes: 237
Reputation: 3651
In Java, method arguments are all passed by value :
Java arguments are all passed by value (the value or reference is copied when used by the method) :
In the case of primitive types, Java behaviour is simple: The value is copied in another instance of the primitive type.
In case of Objects, this is the same: Object variables are references (mem buckets holding only Object’s address instead of a primitive value) that was created using the "new" keyword, and are copied like primitive types.
The behaviour can appear different from primitive types: Because the copied object-variable contains the same address (to the same Object). Object's content/members might still be modified within a method and later access outside, giving the illusion that the (containing) Object itself was passed by reference.
"String" Objects appear to be a good counter-example to the urban legend saying that "Objects are passed by reference":
In effect, using a method, you will never be able, to update the value of a String passed as argument:
A String Object, holds characters by an array declared final that can't be modified. Only the address of the Object might be replaced by another using "new". Using "new" to update the variable, will not let the Object be accessed from outside, since the variable was initially passed by value and copied.
Upvotes: 66
Reputation: 280136
I thought I'd contribute this answer to add more details from the Specifications.
First, What's the difference between passing by reference vs. passing by value?
Passing by reference means the called functions' parameter will be the same as the callers' passed argument (not the value, but the identity
- the variable itself).
Pass by value means the called functions' parameter will be a copy of the callers' passed argument.
Or from wikipedia, on the subject of pass-by-reference
In call-by-reference evaluation (also referred to as pass-by-reference), a function receives an implicit reference to a variable used as argument, rather than a copy of its value. This typically means that the function can modify (i.e. assign to) the variable used as argument—something that will be seen by its caller.
And on the subject of pass-by-value
In call-by-value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function [...]. If the function or procedure is able to assign values to its parameters, only its local copy is assigned [...].
Second, we need to know what Java uses in its method invocations. The Java Language Specification states
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.
So it assigns (or binds) the value of the argument to the corresponding parameter variable.
What is the value of the argument?
Let's consider reference types, the Java Virtual Machine Specification states
There are three kinds of reference types: class types, array types, and interface types. Their values are references to dynamically created class instances, arrays, or class instances or arrays that implement interfaces, respectively.
The Java Language Specification also states
The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.
The value of an argument (of some reference type) is a pointer to an object. Note that a variable, an invocation of a method with a reference type return type, and an instance creation expression (new ...
) all resolve to a reference type value.
So
public void method (String param) {}
...
String variable = new String("ref");
method(variable);
method(variable.toString());
method(new String("ref"));
all bind the value of a reference to a String
instance to the method's newly created parameter, param
. This is exactly what the definition of pass-by-value describes. As such, Java is pass-by-value.
The fact that you can follow the reference to invoke a method or access a field of the referenced object is completely irrelevant to the conversation. The definition of pass-by-reference was
This typically means that the function can modify (i.e. assign to) the variable used as argument—something that will be seen by its caller.
In Java, modifying the variable means reassigning it. In Java, if you reassigned the variable within the method, it would go unnoticed to the caller. Modifying the object referenced by the variable is a different concept entirely.
Primitive values are also defined in the Java Virtual Machine Specification, here. The value of the type is the corresponding integral or floating point value, encoded appropriately (8, 16, 32, 64, etc. bits).
Upvotes: 57
Reputation: 851
Guess, the common canon is wrong based on inaccurate language
Authors of a programming language do not have the authority to rename established programming concept.
Primitive Java types byte, char, short, int, long float, double
are definitely passed by value.
All other types are Objects
: Object members and parameters technically are references.
So these "references" are passed "by value", but there occurs no object construction on the stack. Any change of object members (or elements in case of an array) apply to the same original Object; such reference precisely meets the logic of pointer of an instance passed to some function in any C-dialect, where we used to call this passing an object by reference
Especially we do have this thing java.lang.NullPointerException, which makes no sense in a pure by-value-concept
Upvotes: 1
Reputation: 72
Java uses pass-by-value, but the effects differ whether you are using primitive or a reference type.
When you pass a primitive type as an argument to a method, it's getting a copy of the primitive and any changes inside the block of the method won't change the original variable.
When you pass a reference type as an argument to a method, it's still getting a copy but it's a copy of the reference to the object (in other words, you are getting a copy of the memory address in the heap where the object is located), so any changes in the object inside the block of the method will affect the original object outside the block.
Upvotes: 3
Reputation: 396
For simplicity and verbosity
Its pass reference by value
:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
aDog.getName().equals("Max"); // true
aDog.getName().equals("Fifi"); // false
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// change d inside of foo() to point to a new Dog instance "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
Upvotes: 5
Reputation: 5858
Every single answer here is tying to take pass pointer by reference from other languages and show how it is impossible to do in Java. For whatever reason nobody is attempting to show how to implement pass-object-by-value from other languages.
This code shows how something like this can be done:
public class Test
{
private static void needValue(SomeObject so) throws CloneNotSupportedException
{
SomeObject internalObject = so.clone();
so=null;
// now we can edit internalObject safely.
internalObject.set(999);
}
public static void main(String[] args)
{
SomeObject o = new SomeObject(5);
System.out.println(o);
try
{
needValue(o);
}
catch(CloneNotSupportedException e)
{
System.out.println("Apparently we cannot clone this");
}
System.out.println(o);
}
}
public class SomeObject implements Cloneable
{
private int val;
public SomeObject(int val)
{
this.val = val;
}
public void set(int val)
{
this.val = val;
}
public SomeObject clone()
{
return new SomeObject(val);
}
public String toString()
{
return Integer.toString(val);
}
}
Here we have a function needValue
and what it does is right away create a clone of the object, which needs be implemented in the class of the object itself and the class needs to be marked as Cloneable
. It is not essential to set so
to null
after that, but i have done so here to show that we are not going to be using that reference after that.
It may well be that Java does not have pass-by-reference semantics, but to call the language "pass-by-value" is along the lines of wishful thinking.
Upvotes: -1
Reputation: 263
Here a more precise definition:
So in C/C++ you can create a function that swaps two values passed using the references:
void swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
You can see it has a unique reference to a and b, so we do not have a copy, tmp just hold unique references.
The same function in java does not have side effects, the parameter passing is just like the code above without references.
Although java work with pointers/references, the parameters are not unique pointers, in each attribution, they are copied instead just assigned like C/C++
Upvotes: 4
Reputation: 265
There are only two versions:
Java passes primivates as values and objects as addresses. Those who say, "address are values too", do not make a distinction between the two. Those who focus on the effect of the swap functions focus on what happens after the passing is done.
In C++ you can do the following:
Point p = Point(4,5);
This reserves 8 bytes on the stack and stores (4,5) in it.
Point *x = &p;
This reserves 4 bytes on the stack and stores 0xF43A in it.
Point &y = p;
This reserves 4 bytes on the stack and stores 0xF43A in it.
I think everyone will agree that a call to f(p) is a pass-by-value if the definition of f is f(Point p). In this case an additional 8 bytes being reserved and (4,5) being copied into it. When f changes p the the the original is guarantieed to be unchanged when f returns.
I think that everyone will agree that a call to f(p) is a pass-by-reference if the definition of f is f(Point &p). In this case an additional 4 bytes being reserved and 0xF43A being copied into it. When f changes p the the original is guarantieed to be changed when f returns.
A call to f(&p) is also pass-by-reference if the definition of f is f(Point *p). In this case an additional 4 bytes being reserved and 0xF43A being copied into it. When f changes *p the the original is guarantieed to be changed when f returns.
A call to f(x) is also pass-by-reference if the definition of f is f(Point *p). In this case an additional 4 bytes being reserved and 0xF43A being copied into it. When f changes *p the the original is guarantieed to be changed when f returns.
A call to f(y) is also pass-by-reference if the definition of f is f(Point &p). In this case an additional 4 bytes being reserved and 0xF43A being copied into it. When f changes p the the original is guarantieed to be changed when f returns.
Sure what happens after the passing is done differs, but that is only a language construct. In the case of pointer you have to use -> to access the members and in the case of references you have to use .. If you want to swap the values of the original then you can do tmp=a; a=b; b=tmp; in the case of references and tmp=*a; *b=tmp; *a=tmp for pointers. And in Java you would have do: tmp.set(a); a.set(b); b.set(tmp). Focussing on the assignment statement statement is silly. You can do the exact same thing in Java if you write a little bit of code.
So Java passes primivates by values and objects by references. And Java copy values to achieve that, but so does C++.
For completeness:
Point p = new Point(4,5);
This reserves 4 bytes on the stack and stores 0xF43A in it and reserves 8 bytes on the heap and stores (4,5) in it.
If you want to swap the memory locations like so
void swap(int& a, int& b) {
int *tmp = &a;
&a = &b;
&b = tmp;
}
Then you will find that you run into the limitations of your hardware.
Upvotes: 2
Reputation: 125
If you want it to put into a single sentence to understand and remember easily, simplest answer:
Java is always pass the value with a new reference
(So you can modify the original object but can not access the original reference)
Upvotes: -1
Reputation: 1951
Not to repeat, but one point to those who might still be confused after reading many answers:
pass by value
in Java is NOT EQUAL to pass by value
in C++, though it sounds like that, which is probably why there's confusionBreaking it down:
pass by value
in C++ means passing the value of the object (if object), literarily the copy of the objectpass by value
in Java means passing the address value of the object (if object), not really the "value" (a copy) of the object like C++pass by value
in Java, operating on an object (e.g. myObj.setName("new")
) inside a function has effects on the object outside the function; by pass by value
in C++, it has NO effects on the one outside.pass by reference
in C++, operating on an object in a function DOES have effects on the one outside! Similar (just similar, not the same) to pass by value
in Java, no?.. and people always repeat "there's no pass by reference in Java", => BOOM, confusion starts...So, friends, all is just about the difference of terminology definition (across languages), you just need to know how it works and that's it (though sometimes a bit confusing how it's called I admit)!
Upvotes: 12
Reputation: 9525
I'd say it in another way:
In java references are passed (but not objects) and these references are passed-by-value (the reference itself is copied and you have 2 references as a result and you have no control under the 1st reference in the method).
Just saying: pass-by-value might be not clear enough for beginners. For instance in Python the same situation but there are articles, which describe that they call it pass-by-reference
, only cause references are used.
Upvotes: 5
Reputation: 426
I see that all answers contain the same: pass by value. However, a recent Brian Goetz update on project Valhalla actually answers it differently:
Indeed, it is a common “gotcha” question about whether Java objects are passed by value or by reference, and the answer is “neither”: object references are passed by value.
You can read more here: State of Valhalla. Section 2: Language Model
Edit: Brian Goetz is Java Language Architect, leading such projects as Project Valhalla and Project Amber.
Edit-2020-12-08: Updated State of Valhalla
Upvotes: 15
Reputation: 300
Java always passes parameters by value.
All object references in Java are passed by value. This means that a copy of the value will be passed to a method. But the trick is that passing a copy of the value also changes the real value of the object.
Please refer to the below example,
public class ObjectReferenceExample {
public static void main(String... doYourBest) {
Student student = new Student();
transformIntoHomer(student);
System.out.println(student.name);
}
static void transformIntoDuleepa(Student student) {
student.name = "Duleepa";
}
}
class Student {
String name;
}
In this case, it will be Duleepa!
The reason is that Java object variables are simply references that point to real objects in the memory heap.
Therefore, even though Java passes parameters to methods by value, if the variable points to an object reference, the real object will also be changed.
Upvotes: 7
Reputation: 585
Unlike some other languages, Java does not allow you to choose between pass-by-value and pass-by-reference—all arguments are passed by value. A method call can pass two types of values to a method—copies of primitive values (e.g., values of int and double) and copies of references to objects.
When a method modifies a primitive-type parameter, changes to the parameter have no effect on the original argument value in the calling method.
When it comes to objects, objects themselves cannot be passed to methods. So we pass the reference(address) of the object. We can manipulate the original object using this reference.
How Java creates and stores objects: When we create an object we store the object’s address in a reference variable. Let's analyze the following statement.
Account account1 = new Account();
“Account account1” is the type and name of the reference variable, “=” is the assignment operator, “new” asks for the required amount of space from the system. The constructor to the right of keyword new which creates the object is called implicitly by the keyword new. Address of the created object(result of right value, which is an expression called "class instance creation expression") is assigned to the left value (which is a reference variable with a name and a type specified) using the assign operator.
Although an object’s reference is passed by value, a method can still interact with the referenced object by calling its public methods using the copy of the object’s reference. Since the reference stored in the parameter is a copy of the reference that was passed as an argument, the parameter in the called method and the argument in the calling method refer to the same object in memory.
Passing references to arrays, instead of the array objects themselves, makes sense for performance reasons. Because everything in Java is passed by value, if array objects were passed, a copy of each element would be passed. For large arrays, this would waste time and consume considerable storage for the copies of the elements.
In the image below you can see we have two reference variables(These are called pointers in C/C++, and I think that term makes it easier to understand this feature.) in the main method. Primitive and reference variables are kept in stack memory(left side in images below). array1 and array2 reference variables "point" (as C/C++ programmers call it) or reference to a and b arrays respectively, which are objects (values these reference variables hold are addresses of objects) in heap memory (right side in images below).
If we pass the value of array1 reference variable as an argument to the reverseArray method, a reference variable is created in the method and that reference variable starts pointing to the same array (a).
public class Test
{
public static void reverseArray(int[] array1)
{
// ...
}
public static void main(String[] args)
{
int[] array1 = { 1, 10, -7 };
int[] array2 = { 5, -190, 0 };
reverseArray(array1);
}
}
So, if we say
array1[0] = 5;
in reverseArray method, it will make a change in array a.
We have another reference variable in reverseArray method (array2) that points to an array c. If we were to say
array1 = array2;
in reverseArray method, then the reference variable array1 in method reverseArray would stop pointing to array a and start pointing to array c (Dotted line in second image).
If we return value of reference variable array2 as the return value of method reverseArray and assign this value to reference variable array1 in main method, array1 in main will start pointing to array c.
So let's write all the things we have done at once now.
public class Test
{
public static int[] reverseArray(int[] array1)
{
int[] array2 = { -7, 0, -1 };
array1[0] = 5; // array a becomes 5, 10, -7
array1 = array2; /* array1 of reverseArray starts
pointing to c instead of a (not shown in image below) */
return array2;
}
public static void main(String[] args)
{
int[] array1 = { 1, 10, -7 };
int[] array2 = { 5, -190, 0 };
array1 = reverseArray(array1); /* array1 of
main starts pointing to c instead of a */
}
}
And now that reverseArray method is over, its reference variables(array1 and array2) are gone. Which means we now only have the two reference variables in main method array1 and array2 which point to c and b arrays respectively. No reference variable is pointing to object (array) a. So it is eligible for garbage collection.
You could also assign value of array2 in main to array1. array1 would start pointing to b.
Upvotes: 37
Reputation: 2440
A: Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.
Take the badSwap() method for example:
public void badSwap(int var1, int var2)
{
int temp = var1;
var1 = var2;
var2 = temp;
}
When badSwap() returns, the variables passed as arguments will still hold their original values. The method will also fail if we change the arguments type from int to Object, since Java passes object references by value as well. Now, here is where it gets tricky:
public void tricky(Point arg1, Point arg2)
{
arg1.x = 100;
arg1.y = 100;
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
}
public static void main(String [] args)
{
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
System.out.println("X: " + pnt1.x + " Y: " +pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
System.out.println(" ");
tricky(pnt1,pnt2);
System.out.println("X: " + pnt1.x + " Y:" + pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
}
If we execute this main() method, we see the following output:
X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0
The method successfully alters the value of pnt1, even though it is passed by value; however, a swap of pnt1 and pnt2 fails! This is the major source of confusion. In the main() method, pnt1 and pnt2 are nothing more than object references. When you pass pnt1 and pnt2 to the tricky() method, Java passes the references by value just like any other parameter. This means the references passed to the method are actually copies of the original references. Figure 1 below shows two references pointing to the same object after Java passes an object to a method.
Figure 1. After being passed to a method, an object will have at least two references
Java copies and passes the reference by value, not the object. Thus, method manipulation will alter the objects, since the references point to the original objects. But since the references are copies, swaps will fail.The method references swap, but not the original references. Unfortunately, after a method call, you are left with only the unswapped original references. For a swap to succeed outside of the method call, we need to swap the original references, not the copies.
Upvotes: 8
Reputation: 57
I think this simple explanation might help you understand as I wanted to understand this same thing when I was struggling through this.
When you pass a primitive data to a function call it's content is being copied to the function's argument and when you pass an object it's reference is being copied to the function's argument. Speaking of object, you can't change the copied reference-the argument variable is referencing to in the calling function.
Consider this simple example, String is an object in java and when you change the content of a string the reference variable will now point to some new reference as String objects are immutable in java.
String name="Mehrose"; // name referencing to 100
ChangeContenet(String name){
name="Michael"; // refernce has changed to 1001
}
System.out.print(name); //displays Mehrose
Fairly simple because as I mentioned you are not allowed to change the copied reference in the calling function. But the problem is with the array when you pass an array of String/Object. Let us see.
String names[]={"Mehrose","Michael"};
changeContent(String[] names){
names[0]="Rose";
names[1]="Janet"
}
System.out.println(Arrays.toString(names)); //displays [Rose,Janet]
As we said that we can't change the copied reference in the function call and we also have seen in the case of a single String object. The reason is names[] variable referencing to let's say 200 and names[0] referencing to 205 and so on. You see we didn't change the names[] reference it still points to the old same reference still after the function call but now names[0] and names[1] reference has been changed. We Still stand on our definition that we can't change the reference variable's reference so we didn't.
The same thing happens when you pass a Student object to a method and you are still able to change the Student name or other attributes, the point is we are not changing the actual Student object rather we are changing the contents of it
You can't do this
Student student1= new Student("Mehrose");
changeContent(Student Obj){
obj= new Student("Michael") //invalid
obj.setName("Michael") //valid
}
Upvotes: 3
Reputation: 51
public class Test {
static class Dog {
String name;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public String getName() {
return name;
}
public void setName(String nb) {
this.name = nb;
}
Dog(String sd) {
this.name = sd;
}
}
/**
*
* @param args
*/
public static void main(String[] args) {
Dog aDog = new Dog("Max");
// we pass the object to foo
foo(aDog);
Dog oldDog = aDog;
System.out.println(" 1: " + aDog.getName().equals("Max")); // false
System.out.println(" 2 " + aDog.getName().equals("huahua")); // false
System.out.println(" 3 " + aDog.getName().equals("moron")); // true
System.out.println(" 4 " + " " + (aDog == oldDog)); // true
// part2
Dog aDog1 = new Dog("Max");
foo(aDog1, 5);
Dog oldDog1 = aDog;
System.out.println(" 5 : " + aDog1.getName().equals("huahua")); // true
System.out.println(" part2 : " + (aDog1 == oldDog1)); // false
Dog oldDog2 = foo(aDog1, 5, 6);
System.out.println(" 6 " + (aDog1 == oldDog2)); // true
System.out.println(" 7 " + (aDog1 == oldDog)); // false
System.out.println(" 8 " + (aDog == oldDog2)); // false
}
/**
*
* @param d
*/
public static void foo(Dog d) {
System.out.println(d.getName().equals("Max")); // true
d.setName("moron");
d = new Dog("huahua");
System.out.println(" -:- " + d.getName().equals("huahua")); // true
}
/**
*
* @param d
* @param a
*/
public static void foo(Dog d, int a) {
d.getName().equals("Max"); // true
d.setName("huahua");
}
/**
*
* @param d
* @param a
* @param b
* @return
*/
public static Dog foo(Dog d, int a, int b) {
d.getName().equals("Max"); // true
d.setName("huahua");
return d;
}
}
The sample code to demonstrate the impact of changes to the object at different functions .
Upvotes: 3
Reputation: 338
First let's understand Memory allocation in Java: Stack and Heap are part of Memory that JVM allocates for different purposes. The stack memory is pre-allocated to thread, when it is created, therefore, a thread cannot access the Stack of other thread. But Heap is available to all threads in a program.
For a thread, Stack stores all local data, metadata of program, primitive type data and object reference. And, Heap is responsible for storage of actual object.
Book book = new Book("Effective Java");
In the above example, the reference variable is "book" which is stored in stack. The instance created by new operator -> new Book("Effective Java") is stored in Heap. The ref variable "book" has address of the object allocated in Heap. Let's say the address is 1001.
Consider passing a primitive data type i.e. int, float, double etc.
public class PrimitiveTypeExample {
public static void main(string[] args) {
int num = 10;
System.out.println("Value before calling method: " + num);
printNum(num);
System.out.println("Value after calling method: " + num);
}
public static void printNum(int num){
num = num + 10;
System.out.println("Value inside printNum method: " + num);
}
}
Output is: Value before calling method: 10 Value inside printNum method: 20 Value after calling method: 10
int num =10; -> this allocates the memory for "int" in Stack of the running thread, because, it is a primitive type. Now when printNum(..) is called, a private stack is created within the same thread. When "num" is passed to this method, a copy of "num" is created in the method stack frame. num = num+10; -> this adds 10 and modifies the the int variable within the method stack frame. Therefore, the original num outside the method stack frame remains unchanged.
Consider, the example of passing the object of a custom class as an argument.
In the above example, ref variable "book" resides in stack of thread executing the program, and the object of class Book is created in Heap space when program executes new Book(). This memory location in Heap is referred by "book". When "book" is passed as method argument, a copy of "book" is created in private stack frame of method within the same stack of thread. Therefore, the copied reference variable points to the same object of class "Book" in the Heap.
The reference variable within method stack frame sets a new value to same object. Therefore, it is reflected when original ref variable "book" gets its value. Note that in case of passing reference variable, if it is initialized again in called method, it then points to new memory location and any operation does not affect the previous object in the Heap.
Therefore, when anything is passed as method argument, it is always the Stack entity - either primitive or reference variable. We never pass something that is stored in Heap. Hence, in Java, we always pass the value in the stack, and it is pass by value.
Upvotes: 5