Is Java really passing objects by value? [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is Java pass by reference?
public class myClass{
public static void main(String[] args){
myObject obj = new myObject("myName");
changeName(obj);
System.out.print(obj.getName()); // This prints "anotherName"
}
public static void changeName(myObject obj){
obj.setName("anotherName");
}
}
I know that Java pass by value, but why does it pass obj by reference in previous example and change it?

Java always passes arguments by value, NOT by reference. In your example, you are still passing obj by its value, not the reference itself. Inside your method changeName, you are assigning another (local) reference, obj, to the same object you passed it as an argument. Once you modify that reference, you are modifying the original reference, obj, which is passed as an argument.
EDIT:
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 change the object that the reference 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:
1- Declaring a reference named f of type Foo and assign it to a new object of type Foo with an attribute "f".
Foo f = new Foo("f");
2- From the method side, a reference of type Foo with a name a is declared and it's initially assigned to null.
public static void changeReference(Foo a)
3- As you call the method changeReference, the reference a will be assigned to the object which is passed as an argument.
changeReference(f);
4- Declaring a reference named b of type Foo and assign it to a new object of type Foo with an attribute "b".
Foo b = new Foo("b");
5- a = b is re-assigning the reference a NOT f to the object whose its attribute is "b".
6- As you call modifyReference(Foo c) method, a reference c is created and assigned to the object with attribute "f".
7- c.setAttribute("c"); will change the attribute of the object that reference c points to it, and it's same object that reference f points to it.
I hope you understand now how passing objects as arguments works in Java :)

In Java, an object handle, or the identity of an object is considered a value. Passing by value means passing this handle, not a full copy of the object.
A "reference" in the term "pass by reference" also doesn't mean "reference to an object". It means "reference to a variable" – a named "bucket" in a function definition (or, rather, a call frame) that can store a value.
Passing by reference would mean the called method could change variable values in the calling method. (For example, in the C standard library, the function scanf works this way.) This isn't possible in Java. You can always change the properties of an object – they aren't considered a part of its "value". They're completely different independent objects.

It did not change obj (your code doesn't change it anyway).
Had it been passed by reference, you could have written:
public static void changeName(myObject obj){
obj = new myObject("anotherName");
}
And have "anotherName" printed by the main method.

You're changing a property of obj, not changing obj (the parameter) itself.
The point is that if you pointed obj at something else in changeName that that change would not be reflected in main.
See this post for further clarification.

It is passing the reference to obj as a value (a bit confusing I know :)).
So let's say it makes a copy of the pointer to obj's value and pass that.
That means that you can do things like:
public static void changeName(myObject obj){
obj.setName("anotherName");
obj = new myObject();
}
and the statement
System.out.print(obj.getName());
is still going to refer to the old object (the one that you did setName).

Java is passing a copy of what you're passing to your function. When it is a primitive type - it will be the copy of a value. When it is an object - you're passing the reference copy. In you're code example you're modifying one of objects properties, but not the reference itself so the name will be changed. However when you'd like to assign new object to obj variable in changeName function, then you're changing reference, so outside obj will have an old value.

Related

Java String array changes within a helper method, but reverts within the main method. Why is this? [duplicate]

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?
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 "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
In the example above aDog.getName() will still return "Max". The value aDog within main is not changed in the function foo with the Dog "Fifi" as the object reference is passed by value. If it were 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 the above example, Fifi is the 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.
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.
the parameter someDog is set to the value 42
at line "AAA"
someDog is followed to the Dog it points to (the Dog object at address 42)
that Dog (the one at address 42) is asked to change his name to Max
at line "BBB"
a new Dog is created. Let's say he's at address 74
we assign the parameter someDog to 74
at line "CCC"
someDog is followed to the Dog it points to (the Dog object at address 74)
that Dog (the one at address 74) is asked to change his name to Rowlf
then, we return
Now 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.
Update
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.
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.
I hope you understand now how passing objects as arguments works in Java :)
Java is always pass by value, with no exceptions, ever.
So how is it that anyone can be at all confused by this, and believe that Java is pass by reference, or think they have an example of Java acting as pass by reference? The key point is that Java never provides direct access to the values of objects themselves, in any circumstances. The only access to objects is through a reference to that object. Because Java objects are always accessed through a reference, rather than directly, it is common to talk about fields and variables and method arguments as being objects, when pedantically they are only references to objects. The confusion stems from this (strictly speaking, incorrect) change in nomenclature.
So, when calling a method
For primitive arguments (int, long, etc.), the pass by value is the actual value of the primitive (for example, 3).
For objects, the pass by value is the value of the reference to the object.
So if you have doSomething(foo) and public void doSomething(Foo foo) { .. } the two Foos have copied references that point to the same objects.
Naturally, passing by value a reference to an object looks very much like (and is indistinguishable in practice from) passing an object by reference.
This will give you some insights of how Java really works to the point that in your next discussion about Java passing by reference or passing by value you'll just smile :-)
Step one please erase from your mind that word that starts with 'p' "_ _ _ _ _ _ _", especially if you come from other programming languages. Java and 'p' cannot be written in the same book, forum, or even txt.
Step two remember that when you pass an Object into a method you're passing the Object reference and not the Object itself.
Student: Master, does this mean that Java is pass-by-reference?
Master: Grasshopper, No.
Now think of what an Object's reference/variable does/is:
A variable holds the bits that tell the JVM how to get to the referenced Object in memory (Heap).
When passing arguments to a method you ARE NOT passing the reference variable, but a copy of the bits in the reference variable. Something like this: 3bad086a. 3bad086a represents a way to get to the passed object.
So you're just passing 3bad086a that it's the value of the reference.
You're passing the value of the reference and not the reference itself (and not the object).
This value is actually COPIED and given to the method.
In the following (please don't try to compile/execute this...):
1. Person person;
2. person = new Person("Tom");
3. changeName(person);
4.
5. //I didn't use Person person below as an argument to be nice
6. static void changeName(Person anotherReferenceToTheSamePersonObject) {
7. anotherReferenceToTheSamePersonObject.setName("Jerry");
8. }
What happens?
The variable person is created in line #1 and it's null at the beginning.
A new Person Object is created in line #2, stored in memory, and the variable person is given the reference to the Person object. That is, its address. Let's say 3bad086a.
The variable person holding the address of the Object is passed to the function in line #3.
In line #4 you can listen to the sound of silence
Check the comment on line #5
A method local variable -anotherReferenceToTheSamePersonObject- is created and then comes the magic in line #6:
The variable/reference person is copied bit-by-bit and passed to anotherReferenceToTheSamePersonObject inside the function.
No new instances of Person are created.
Both "person" and "anotherReferenceToTheSamePersonObject" hold the same value of 3bad086a.
Don't try this but person==anotherReferenceToTheSamePersonObject would be true.
Both variables have IDENTICAL COPIES of the reference and they both refer to the same Person Object, the SAME Object on the Heap and NOT A COPY.
A picture is worth a thousand words:
Note that the anotherReferenceToTheSamePersonObject arrows is directed towards the Object and not towards the variable person!
If you didn't get it then just trust me and remember that it's better to say that Java is pass by value. Well, pass by reference value. Oh well, even better is pass-by-copy-of-the-variable-value! ;)
Now feel free to hate me but note that given this there is no difference between passing primitive data types and Objects when talking about method arguments.
You always pass a copy of the bits of the value of the reference!
If it's a primitive data type these bits will contain the value of the primitive data type itself.
If it's an Object the bits will contain the value of the address that tells the JVM how to get to the Object.
Java is pass-by-value because inside a method you can modify the referenced Object as much as you want but no matter how hard you try you'll never be able to modify the passed variable that will keep referencing (not p _ _ _ _ _ _ _) the same Object no matter what!
The changeName function above will never be able to modify the actual content (the bit values) of the passed reference. In other word changeName cannot make Person person refer to another Object.
Of course you can cut it short and just say that Java is pass-by-value!
Java passes references by value.
So you can't change the reference that gets passed in.
I feel like arguing about "pass-by-reference vs pass-by-value" is not super-helpful.
If you say, "Java is pass-by-whatever (reference/value)", in either case, you're not provide a complete answer. Here's some additional information that will hopefully aid in understanding what's happening 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".
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.
Just to show the contrast, compare the following C++ and Java snippets:
In C++: Note: Bad code - memory leaks! But it demonstrates the point.
void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
val = 7; // Modifies the copy
ref = 7; // Modifies the original variable
obj.SetName("obj"); // Modifies the copy of Dog passed
objRef.SetName("objRef"); // Modifies the original Dog passed
objPtr->SetName("objPtr"); // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to
// by the original pointer passed.
objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}
int main()
{
int a = 0;
int b = 0;
Dog d0 = Dog("d0");
Dog d1 = Dog("d1");
Dog *d2 = new Dog("d2");
Dog *d3 = new Dog("d3");
cppMethod(a, b, d0, d1, d2, d3);
// a is still set to 0
// b is now set to 7
// d0 still have name "d0"
// d1 now has name "objRef"
// d2 now has name "objPtr"
// d3 now has name "newObjPtrRef"
}
In Java,
public static void javaMethod(int val, Dog objPtr)
{
val = 7; // Modifies the copy
objPtr.SetName("objPtr") // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
}
public static void main()
{
int a = 0;
Dog d0 = new Dog("d0");
javaMethod(a, d0);
// a is still set to 0
// d0 now has name "objPtr"
}
Java only has the two types of passing: by value for built-in types, and by value of the pointer for object types.
Java passes references to objects by value.
I can't believe that nobody mentioned Barbara Liskov yet. When she designed CLU in 1974, she ran into this same terminology problem, and she invented the term call by sharing (also known as call by object-sharing and call by object) for this specific case of "call by value where the value is a reference".
The crux of the matter is that the word reference in the expression "pass by reference" means something completely different from the usual meaning of the word reference in Java.
Usually in Java reference means a a reference to an object. But the technical terms pass by reference/value from programming language theory is talking about a reference to the memory cell holding the variable, which is something completely different.
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.
In java everything is reference, so when you have something like:
Point pnt1 = new Point(0,0); Java does following:
Creates new Point object
Creates new Point reference and initialize that reference to point (refer to) on previously created Point object.
From here, through Point object life, you will access to that object through pnt1
reference. So we can say that in Java you manipulate object through its reference.
Java doesn't pass method arguments by reference; it passes them by value. I will use example from this site:
public static 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("X1: " + pnt1.x + " Y1: " +pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
tricky(pnt1,pnt2);
System.out.println("X1: " + pnt1.x + " Y1:" + pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
}
Flow of the program:
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
Creating two different Point object with two different reference associated.
System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
As expected output will be:
X1: 0 Y1: 0
X2: 0 Y2: 0
On this line 'pass-by-value' goes into the play...
tricky(pnt1,pnt2); public void tricky(Point arg1, Point arg2);
References pnt1 and pnt2 are passed by value to the tricky method, which means that now yours references pnt1 and pnt2 have their copies named arg1 and arg2.So pnt1 and arg1 points to the same object. (Same for the pnt2 and arg2)
In the tricky method:
arg1.x = 100;
arg1.y = 100;
Next in the tricky method
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
Here, you first create new temp Point reference which will point on same place like arg1 reference. Then you move reference arg1 to point to the same place like arg2 reference.
Finally arg2 will point to the same place like temp.
From here scope of tricky method is gone and you don't have access any more to the references: arg1, arg2, temp. But important note is that everything you do with these references when they are 'in life' will permanently affect object on which they are point to.
So after executing method tricky, when you return to main, you have this situation:
So now, completely execution of program will be:
X1: 0 Y1: 0
X2: 0 Y2: 0
X1: 100 Y1: 100
X2: 0 Y2: 0
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:
Hopefully this will help.
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.
A reference is always a value when represented, no matter what language you use.
Getting an outside of the box view, let's look at Assembly or some low level memory management. At the CPU level a reference to anything immediately becomes a value if it gets written to memory or to one of the CPU registers. (That is why pointer is a good definition. It is a value, which has a purpose at the same time).
Data in memory has a Location and at that location there is a value (byte,word, whatever). In Assembly we have a convenient solution to give a Name to certain Location (aka variable), but when compiling the code, the assembler simply replaces Name with the designated location just like your browser replaces domain names with IP addresses.
Down to the core it is technically impossible to pass a reference to anything in any language without representing it (when it immediately becomes a value).
Lets say we have a variable Foo, its Location is at the 47th byte in memory and its Value is 5. We have another variable Ref2Foo which is at 223rd byte in memory, and its value will be 47. This Ref2Foo might be a technical variable, not explicitly created by the program. If you just look at 5 and 47 without any other information, you will see just two Values.
If you use them as references then to reach to 5 we have to travel:
(Name)[Location] -> [Value at the Location]
---------------------
(Ref2Foo)[223] -> 47
(Foo)[47] -> 5
This is how jump-tables work.
If we want to call a method/function/procedure with Foo's value, there are a few possible way to pass the variable to the method, depending on the language and its several method invocation modes:
5 gets copied to one of the CPU registers (ie. EAX).
5 gets PUSHd to the stack.
47 gets copied to one of the CPU registers
47 PUSHd to the stack.
223 gets copied to one of the CPU registers.
223 gets PUSHd to the stack.
In every cases above a value - a copy of an existing value - has been created, it is now upto the receiving method to handle it. When you write "Foo" inside the method, it is either read out from EAX, or automatically dereferenced, or double dereferenced, the process depends on how the language works and/or what the type of Foo dictates. This is hidden from the developer until she circumvents the dereferencing process. So a reference is a value when represented, because a reference is a value that has to be processed (at language level).
Now we have passed Foo to the method:
in case 1. and 2. if you change Foo (Foo = 9) it only affects local scope as you have a copy of the Value. From inside the method we cannot even determine where in memory the original Foo was located.
in case 3. and 4. if you use default language constructs and change Foo (Foo = 11), it could change Foo globally (depends on the language, ie. Java or like Pascal's procedure findMin(x, y, z: integer;var m: integer);). However if the language allows you to circumvent the dereference process, you can change 47, say to 49. At that point Foo seems to have been changed if you read it, because you have changed the local pointer to it. And if you were to modify this Foo inside the method (Foo = 12) you will probably FUBAR the execution of the program (aka. segfault) because you will write to a different memory than expected, you can even modify an area that is destined to hold executable program and writing to it will modify running code (Foo is now not at 47). BUT Foo's value of 47 did not change globally, only the one inside the method, because 47 was also a copy to the method.
in case 5. and 6. if you modify 223 inside the method it creates the same mayhem as in 3. or 4. (a pointer, pointing to a now bad value, that is again used as a pointer) but this is still a local problem, as 223 was copied. However if you are able to dereference Ref2Foo (that is 223), reach to and modify the pointed value 47, say, to 49, it will affect Foo globally, because in this case the methods got a copy of 223 but the referenced 47 exists only once, and changing that to 49 will lead every Ref2Foo double-dereferencing to a wrong value.
Nitpicking on insignificant details, even languages that do pass-by-reference will pass values to functions, but those functions know that they have to use it for dereferencing purposes. This pass-the-reference-as-value is just hidden from the programmer because it is practically useless and the terminology is only pass-by-reference.
Strict pass-by-value is also useless, it would mean that a 100 Mbyte array should have to be copied every time we call a method with the array as argument, therefore Java cannot be stricly pass-by-value. Every language would pass a reference to this huge array (as a value) and either employs copy-on-write mechanism if that array can be changed locally inside the method or allows the method (as Java does) to modify the array globally (from the caller's view) and a few languages allows to modify the Value of the reference itself.
So in short and in Java's own terminology, Java is pass-by-value where value can be: either a real value or a value that is a representation of a reference.
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.
As far as I know, Java only knows call by value. This means for primitive datatypes you will work with an copy and for objects you will work with an copy of the reference to the objects. However I think there are some pitfalls; for example, this will not work:
public static void swap(StringBuffer s1, StringBuffer s2) {
StringBuffer temp = s1;
s1 = s2;
s2 = temp;
}
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("Hello");
StringBuffer s2 = new StringBuffer("World");
swap(s1, s2);
System.out.println(s1);
System.out.println(s2);
}
This will populate Hello World and not World Hello because in the swap function you use copys which have no impact on the references in the main. But if your objects are not immutable you can change it for example:
public static void appendWorld(StringBuffer s1) {
s1.append(" World");
}
public static void main(String[] args) {
StringBuffer s = new StringBuffer("Hello");
appendWorld(s);
System.out.println(s);
}
This will populate Hello World on the command line. If you change StringBuffer into String it will produce just Hello because String is immutable. For example:
public static void appendWorld(String s){
s = s+" World";
}
public static void main(String[] args) {
String s = new String("Hello");
appendWorld(s);
System.out.println(s);
}
However you could make a wrapper for String like this which would make it able to use it with Strings:
class StringWrapper {
public String value;
public StringWrapper(String value) {
this.value = value;
}
}
public static void appendWorld(StringWrapper s){
s.value = s.value +" World";
}
public static void main(String[] args) {
StringWrapper s = new StringWrapper("Hello");
appendWorld(s);
System.out.println(s.value);
}
edit: i believe this is also the reason to use StringBuffer when it comes to "adding" two Strings because you can modifie the original object which u can't with immutable objects like String is.
No, it's not pass by reference.
Java is pass by value according to the Java Language Specification:
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.
Let me try to explain my understanding with the help of four examples. Java is pass-by-value, and not pass-by-reference
/**
Pass By Value
In Java, all parameters are passed by value, i.e. assigning a method argument is not visible to the caller.
*/
Example 1:
public class PassByValueString {
public static void main(String[] args) {
new PassByValueString().caller();
}
public void caller() {
String value = "Nikhil";
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
Result
output : output
value : Nikhil
valueflag : false
Example 2:
/**
*
* Pass By Value
*
*/
public class PassByValueNewString {
public static void main(String[] args) {
new PassByValueNewString().caller();
}
public void caller() {
String value = new String("Nikhil");
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
Result
output : output
value : Nikhil
valueflag : false
Example 3:
/**
This 'Pass By Value has a feeling of 'Pass By Reference'
Some people say primitive types and 'String' are 'pass by value'
and objects are 'pass by reference'.
But from this example, we can understand that it is infact pass by value only,
keeping in mind that here we are passing the reference as the value.
ie: reference is passed by value.
That's why are able to change and still it holds true after the local scope.
But we cannot change the actual reference outside the original scope.
what that means is demonstrated by next example of PassByValueObjectCase2.
*/
public class PassByValueObjectCase1 {
private class Student {
int id;
String name;
public Student() {
}
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
public static void main(String[] args) {
new PassByValueObjectCase1().caller();
}
public void caller() {
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student);
}
public String method(Student student) {
student.setName("Anand");
return "output";
}
}
Result
output : output
student : Student [id=10, name=Anand]
Example 4:
/**
In addition to what was mentioned in Example3 (PassByValueObjectCase1.java), we cannot change the actual reference outside the original scope."
Note: I am not pasting the code for private class Student. The class definition for Student is same as Example3.
*/
public class PassByValueObjectCase2 {
public static void main(String[] args) {
new PassByValueObjectCase2().caller();
}
public void caller() {
// student has the actual reference to a Student object created
// can we change this actual reference outside the local scope? Let's see
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student); // Will it print Nikhil or Anand?
}
public String method(Student student) {
student = new Student(20, "Anand");
return "output";
}
}
Result
output : output
student : Student [id=10, name=Nikhil]
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).
You can never pass by reference in Java, and one of the ways that is obvious is when you want to return more than one value from a method call. Consider the following bit of code in C++:
void getValues(int& arg1, int& arg2) {
arg1 = 1;
arg2 = 2;
}
void caller() {
int x;
int y;
getValues(x, y);
cout << "Result: " << x << " " << y << endl;
}
Sometimes you want to use the same pattern in Java, but you can't; at least not directly. Instead you could do something like this:
void getValues(int[] arg1, int[] arg2) {
arg1[0] = 1;
arg2[0] = 2;
}
void caller() {
int[] x = new int[1];
int[] y = new int[1];
getValues(x, y);
System.out.println("Result: " + x[0] + " " + y[0]);
}
As was explained in previous answers, in Java you're passing a pointer to the array as a value into getValues. That is enough, because the method then modifies the array element, and by convention you're expecting element 0 to contain the return value. Obviously you can do this in other ways, such as structuring your code so this isn't necessary, or constructing a class that can contain the return value or allow it to be set. But the simple pattern available to you in C++ above is not available in Java.
The distinction, or perhaps just the way I remember as I used to be under the same impression as the original poster is this: Java is always pass by value. All objects( in Java, anything except for primitives) in Java are references. These references are passed by value.
As many people mentioned it before, Java is always pass-by-value
Here is another example that will help you understand the difference (the classic swap example):
public class Test {
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(3);
System.out.println("Before: a = " + a + ", b = " + b);
swap(a,b);
System.out.println("After: a = " + a + ", b = " + b);
}
public static swap(Integer iA, Integer iB) {
Integer tmp = iA;
iA = iB;
iB = tmp;
}
}
Prints:
Before: a = 2, b = 3
After: a = 2, b = 3
This happens because iA and iB are new local reference variables that have the same value of the passed references (they point to a and b respectively). So, trying to change the references of iA or iB will only change in the local scope and not outside of this method.
I always think of it as "pass by copy". It is a copy of the value be it primitive or reference. If it is a primitive it is a copy of the bits that are the value and if it is an Object it is a copy of the reference.
public class PassByCopy{
public static void changeName(Dog d){
d.name = "Fido";
}
public static void main(String[] args){
Dog d = new Dog("Maxx");
System.out.println("name= "+ d.name);
changeName(d);
System.out.println("name= "+ d.name);
}
}
class Dog{
public String name;
public Dog(String s){
this.name = s;
}
}
output of java PassByCopy:
name= Maxx
name= Fido
Primitive wrapper classes and Strings are immutable so any example using those types will not work the same as other types/objects.
Java has only pass by value. A very simple example to validate this.
public void test() {
MyClass obj = null;
init(obj);
//After calling init method, obj still points to null
//this is because obj is passed as value and not as reference.
}
private void init(MyClass objVar) {
objVar = new MyClass();
}
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.
To make a long story short, Java objects have some very peculiar properties.
In general, Java has primitive types (int, bool, char, double, etc) that are passed directly by value. Then Java has objects (everything that derives from java.lang.Object). Objects are actually always handled through a reference (a reference being a pointer that you can't touch). That means that in effect, objects are passed by reference, as the references are normally not interesting. It does however mean that you cannot change which object is pointed to as the reference itself is passed by value.
Does this sound strange and confusing? Let's consider how C implements pass by reference and pass by value. In C, the default convention is pass by value. void foo(int x) passes an int by value. void foo(int *x) is a function that does not want an int a, but a pointer to an int: foo(&a). One would use this with the & operator to pass a variable address.
Take this to C++, and we have references. References are basically (in this context) syntactic sugar that hide the pointer part of the equation: void foo(int &x) is called by foo(a), where the compiler itself knows that it is a reference and the address of the non-reference a should be passed. In Java, all variables referring to objects are actually of reference type, in effect forcing call by reference for most intends and purposes without the fine grained control (and complexity) afforded by, for example, C++.
I have created a thread devoted to these kind of questions for any programming languages here.
Java is also mentioned. Here is the short summary:
Java passes it parameters by value
"by value" is the only way in java to pass a parameter to a method
using methods from the object given as parameter will alter the
object as the references point to
the original objects. (if that
method itself alters some values)

Unable to understand the issue "call By Reference" [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
In Java, object reference is used for call by reference and variables are used for call by value.
Here’s an example:
class Foo{
int x;
int y;
}
public class CallByRef {
public static void main(String[] args) {
Foo foo = new Foo();
foo.x=5;
foo.y=10;
System.out.println(foo.x+", "+foo.y);
getFoo(foo);
System.out.println(foo.x+", "+foo.y);
}
static void getFoo(Foo f){
f.x=2;
f=new Foo();
f.x=10;
}
}
Output:
5, 10
2, 10
Why this is happend?
x should be 10 as I modified its value with f.x=10
Is it correct that f=new Foo() will create new object in heap and not point to prevoise reference?
In method getFoo, variable f is a local variable.
When you call getFoo(foo) from main, this variable indeed refers to foo.
But once you set f = new Foo(), it refers to a different object.
Therefore, at that point, changing f.x does not affect foo.x.
Here is a basic description what happens in your case as an example
// Creating a new object of Foo
// The variable foo now stores a VALUE!!! to the memory where the
// Instance of foo is stored
Foo foo = new Foo();
// accesing the instance of Foo over the value to the reference in the memory
// and set x to 5
foo.x = 5
// accesing the instance of Foo over the value to the reference in the memory
// and set y to 5
foo.x = 10
// Print out x and y of the instance of Foo where the value of the reference to memeory points to
System.out.println(foo.x+", "+foo.y);
now to what get Foo does
// The instance f of Foo holds the value to the reference in the memory
// Lets call it 1234567 as example
static void getFoo(Foo f){
// The object in the memory 1234567 is going to have x changed
f.x=2;
// The VALUE of the reference is changed, lets say it now refers to the memory 123456789 where a new instance of Foo is stored now
f=new Foo();
// The object in the memory 123456789 is going to have x changed
f.x=10;
}
Lets go back to your last output and what it does print now
// So in your getFoo() Call your first action was to change the value of x
// on the object with the value to the reference which you gave as a parameter
// hence it prints 2
// The new instance of the Object Foo that is stored somewhere else in the memory should be garbage collected soon, since no variable actually holds the VALUE to the reference anymore
System.out.println(foo.x+", "+foo.y);
The most import part to understand is, that the references to the object in a variable or parameter are actually stored as values to the memory. Due to this your getFoo() method simply changes the value of the reference to the instance of the object, but can never change the reference itself
I think first case is clear for you, ie the value 5,10.
After that by calling getFoo() method and passing the same object foo is passing as argument. And in getFoo() method the instance variable value of the same object(foo) is changed to 2. But after that it s creating new object using new keywork and assigning another value.
ie.
foo => x=2(new value) and y=10(not changed, so it takes old value)
f => x=10 and y=0(not assigned)
And you are printing foo's values.
Hence the result 2,10

Understanding the concept of Java being pass by value? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
One of the most popular answers to one of the most popular questions in Java here reads:
Java is always pass-by-value. The difficult thing to understand is that Java passes objects as references and those references are passed by value.
So what does "Java passes objects as references and those references are passed by value." mean?
Does it mean that:
The memory location to which the original variable points is copied as the value of the new temporary variable? (if this is the case, all the changes made inside the function will be reflected in the original, right?)
If not, what does it mean?
Think of objects references as "pointers to a value"
When you pass a value into a method, you pass the pointer in, therefore the two pointers (the one in the method, and the one you passed in) point to the same thing.
Consider this
public static void main(String[] args){
Foo cl = new Foo();
cl.z= 100;
method(cl);
System.out.println(cl.z);
}
private static void method(Foo bar){
bar.z=10;
}
Before you call method, cl.z would be 100, but after you pass it in, it would be equal to 10.
What is not correct is this:
public static void main(String[] args){
Foo cl = new Foo();
cl.z= 100;
method(cl);
System.out.println(cl.z);
}
private static void method(Foo bar){
bar = new Foo();
bar.z=10000;
}
This would NOT print out 10000, because you cannot assign the pointer to reference a different object
When we say Java is pass-by-value, it means that if you modify a parameter inside a method, it has no effect on the caller. For example:
public void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
All this does is swap local copies of the parameters. Thus, if you say
int x = something;
int y = somethingElse;
swap(x, y);
x and y would not change.
The same is true for references:
public void someOperation(MyClass a) {
a = ...something...;
}
Inside your method, a is a copy of whatever reference you pass in; if you reassign a to something else in the method, it doesn't affect any variable in the caller.
MyClass x = ...;
someOperation(x);
x does not change, even though you've changed the parameter a inside the method.
Note that this means that x itself will not change. It will not point to a different MyClass instance, even though a in the method was changed to refer to a different MyClass instance. However, even though the reference does not changed, the object that the reference refers to could be changed by the method.
It means the reference (a memory pointer to the object) is passed by value. If you modify the object, you modify the reference to the object; thus the change will be seen across your application. If you modify the pointer, then your only change it for the scope of your method.
void method(Foo f) {
f.bar = 10; // Seen accross your application.
f = new Foo(); // Modifying your pointer. This does not change the previous object.
}
Yes, Java is always pass-by-value, with both reference types and primitive types. But that doesn't mean that changes within functions always affect the object passed in as an argument.
If a primitive type is passed in, then there is no reference passed, it's by pure value, and any values in the calling scope will not change.
If a reference type is passed in, whether or not a function can modify it depends upon if the type is mutable (the object can be modified) or immutable (the object itself cannot be modified, a new object must be created for all modifications).
If it is mutable, like StringBuilder or HashMap<String, String>, then the function is able to modify it and changes within the function will still be in place after the function call returns. However, note that changing what a reference type points to is not modifying it, in that case, you are only changing what the reference type points to, not the original object referenced by an argument, but doing an operation like strbuilder.append("xyz") is.
If it is immutable, like String or Integer then all modifications within the function will create a new object and the changes will not be in place after the function call returns.

reference type in Java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is Java pass-by-reference?
Java pass by reference
For the following Java program, my understanding is that a is a reference type to an Integer, like pointer type in C/C++. So any changes done in method f to its value will be reflected after the method returns. But println still prints its original value 0 instead of 3.
Integer and int does not make a difference. Was my previous understanding wrong? Please help. Thank you!
public static void f(Integer b){
b=3;
}
public static void main(String[] args){
Integer a=0;
f(a);
System.out.println(a);
}
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 to 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 to null.
public static void changeReference(Foo a)
As you call the method changeReference, the reference a will be assigned to the object which is passed as an argument.
changeReference(f);
Declaring a reference named b of type Foo and assign it to a new object of type Foo with an attribute "b".
Foo b = new Foo("b");
a = b is re-assigning the reference a NOT f to the object whose its attribute is "b".
As you call modifyReference(Foo c) method, a reference c is created and assigned to the object with attribute "f".
c.setAttribute("c"); will change the attribute of the object that reference c points to it, and it's same object that reference f points to it.
I hope you understand now how passing objects as arguments works in Java :)
Integer (like other "basic" classes) are inmutable objects. It means that there is no method by which you can change the value. If you do
new Integer(1);
the object created will always hold the 1 value.
Of course you can do
Integer a = new Integer(1);
a = new Integer(2);
but here what you are doing is creating two objects, and assigning a to each of them in turn.
When calling the method, you are passing a copy of the reference in a (as edalorzo said), so you are doing pretty much the same (but without changing the original a reference).
Of course, lots of classes are not inmutable. In these classes, you would have one (or several) methods that allow you to change the object inner state, and (as long as you are accessing the same object) these changes would be "shared" by all the references of the object (since they all point to the same one). For example, suppose Integer had a setValue(int) method, then
public static void f(Integer b){
b.setValue(3);
}
public static void main(String[] args){
Integer a=0;
f(a);
System.out.println(a);
}
Would work as you expected.
The method receives a copy of the reference. The assignment doesn't change the value that the integer represents (it couldn't even if it wanted to - Integer is immutable in Java). It is just setting b to point at something else. The original Integer object that a is pointing to is unaffected by this change.
Before b = 3;
------ ------
| a | | b |
------ ------
| |
------------
|
Integer(0)
After b = 3;
------ ------
| a | | b |
------ ------
| |
| |
| |
Integer(0) Integer(3)
If you wanted to change the value you'd have to use a mutable type instead.
Related
Does Java have mutable types for Integer, Float, Double, Long?
Integer is immutable so the passing by reference won't work as expected. see Java : Best way to pass int by reference
In Java everything is pass-by-copy, in your method you are chaining the reference, not the actual object it is pointing to.
Your understanding was right but Integers are immutable. If you want to affect the value of a Integer variable, the only way is to create a new Integer object and discard the old one. For this reason, the statement b=3 has no effect.

Immutable and pass by value

I have the following code which has
a mutable Person class, String and a method to modify the instances of String and Person
class Person{
int a = 8;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
#Override
public String toString() {
return "Person [a=" + a + "]";
}
}
--
public class TestMutable {
public static void main(String[] args)
{
Person p = new Person();
p.setA(34);
String s = "bar";
modifyObject(s, p); //Call to modify objects
System.out.println(s);
System.out.println(p);
}
private static void modifyObject(String str, Person p)
{
str = "foo";
p.setA(45);
}
}
The output is as expected. It prints
bar
Person [a=45]
Now, my question is
What is happening at the place you say str="foo" ?
Initially let's assume that s='bar' and the data resides in 0x100 memory
Now the reference of string is passed to another method, the other method tries to change the contents of the memory location(0x100) to 'foo' using s="foo". Is this what is happening, or is 'foo' is created in differennt memory location ?
Does java pass references by value ?
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 change 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:
1- Declaring a reference named f of type Foo and assign it to a new object of type Foo with an attribute "f".
Foo f = new Foo("f");
2- From the method side, a reference of type Foo with a name a is declared and it's initially assigned to null.
public static void changeReference(Foo a)
3- As you call the method changeReference, the reference a will be assigned to the object which is passed as an argument.
changeReference(f);
4- Declaring a reference named b of type Foo and assign it to a new object of type Foo with an attribute "b".
Foo b = new Foo("b");
5- a = b is re-assigning the reference a NOT f to the object whose its attribute is "b".
6- As you call modifyReference(Foo c) method, a reference c is created and assigned to the object with attribute "f".
7- c.setAttribute("c"); will change the attribute of the object that reference c points to it, and it's same object that reference f points to it.
I hope you understand now how passing objects as arguments works in Java :)
In modifyObject, When you assign to str, you're not mutating str, you're setting it so that it points to a different object. Since it's passed by value, the str pointer local to your modifyObject method is a copy of the s pointer in main, so when you change the former, it does not affect le later.
On the other hand, when it comes to p, the one in modifyObject is still a copy of the one in main, but both pointers refer to the very same object in memory, hence if you call a method on it from modifyObject, you're actually mutating the thing pointed to by p.
Sometimes people get confused when passing by reference. It's possible to change the object that the reference refers to (giving the impression of pass-by-reference), but it is not possible to modify reference itself. So it still remains pass-by-value.
In this function call "modifyObject(s, p);" you are sending the value of variable s to modifyObject method's local variable str. So a new variable is created and its value is changed but the original one remains unchanged.

Categories