This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
Ok, so I am a relatively new programmer. I have read over and over about passing variables. From what I have read here is what I've come to understand: In Java, when you pass a variable to a method (be it primitive or Object) you are ALWAYS passing by value. But what you are REALLY doing is passing a copy of the reference to an object or variable in memory.
So why do they call it pass by value? It seems to me you are passing by reference. Also, in C when you pass a pointer to a function, aren't you passing the address of a variable in memory? Yet it is called pass by value. What am I overlooking? Can someone please explain and clarify why I this? I know how to pass variables and such and I have read several SO posts on this but I am not fully satisfied yet. Consider an example:
static void setNameStatic(Dog d, String name) {
d.name = name;
}
public static void main (String args[]) {
Dog d = new Dog("dog1");
System.out.println( d.getName() );
setNameStatic( d, "dog2" );
System.out.println( d.getName() );
}
Won't this output: dog1 and dog2. So aren't you going to where the reference is referring to and changing data around? What exactly does the value have to do with here? Any helpful comments are appreciated. And yes, I know it is pass by value, but why isn't it called "pass by sending copy of reference" lol?
Update: Thanks to everyone that gave a helpful answer. I know this was marked duplicate, and sorry about that. I am satisfied with the answers now.
Your memory looks like this at the moment of:
Dog d = new Dog("dog1");
Stack (with local vars) Heap
+-----------+ points to
| Dog d | ---------------> real dog object
+-----------+
| ... |
+-----------+
| ... |
+-----------+
And then, when you pass in a reference to a method, it looks something like this (where the Dog dog2 is the method argument):
Stack (with local vars) Heap
+-----------+
| Dog d | ---------------> real dog object
+-----------+ ^
| ... | |
+-----------+ |
| Dog d2 |------------------------------
+-----------+
So, the reference is passed by value. It points to the same object but it is the new reference!
Meaning, if you would try something like this:
public static void main(String ... args) {
Dog d= new Dog("dog1");
setNameStatic(d, "dog2");
System.out.println(d); // Still prints dog1 !!!
}
static void setNameStatic(Dog d2, String name) {
d2= new Dog(name);
}
Because the new (copied) reference now points to the new object on heap and the original object has not changed.
Because the value of any variable of reference type is its address in memory.
Because the value of any variable of primitive type is its value itself.
So you always pass values of variables.
Every variable is passed by value. In the instance of primatives, we have the naive case - the values are passed into the function.
In the instance of Objects, we have a slightly more complicated although analogous paradigm - the references to the objects are passed by value.
Note the subtle differences:
//This is essentially a no-op. The values are only local to the function
void swap(int a, int b){
int temp = a;
a = b;
b = temp;
}
//This is different. The references to a and b are passed by value so the values of a.x and b.x are actually swapped on return.
void swap(Point a, Point b){
int temp = a.x;
a.x = b.x;
b.x = temp;
}
Passing by value means that the value is transferred to method, i.e. yet another copy of the same value is created:
int i = 5; // one copy of 5
foo(i);
private void foo(int n) {
// here n is 5, however it is "another" 5
}
The evidence of passing by value is that you cannot change your i from within the method foo():
int i = 5; // one copy of 5
foo(i);
// i is still 5 here
private void foo(int n) {
n = 6;
// n is 6, however it is actual inside the method only.
}
The same is with objects, however in that case reference is passed by value.
Also, in C when you pass a pointer to a function, aren't you passing the address of a variable in memory? Yet it is called pass by value.
No it is not. When you pass a pointer to a value to a function in C, it is known as 'pass by reference'. The function can directly access & modify the original value because it has it's address. Pass by value is when you pass the value of objects instead of their locations or addresses. Look at the following examples.
int addOne(int x)
{
return x + 1;
}
void destructiveAddOne(int *x)
{
*x += 1;
}
int main(void)
{
int x = 5;
int y = 5;
// We pass the _value_ of x, ie, 5 to addOne, and store the result in z.
// The value of x will remain unchanged, ie, 5.
int z = addOne(x);
// We pass a REFERENCE to y, ie, it's address to destructiveAddOne()
// destructiveAddOne then modifies the value of y to be y + 1. The value of y
// has now CHANGED to 6. This is call by reference.
destructiveAddOne(&y);
return 0;
}
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.
Had that before:
Is Java "pass-by-reference" or "pass-by-value"?
It is a tricky thing to get your head round. I think of it as real numbers, albeit abstracted. Say your first dog, dog1, is created at memory location "100,000" (I know but bear with me). You pass the reference's value of 100,000 around to methods. Your method changes the name of the object living at 100,000.
If you pass your dog1 object into a method that does d = new Dog("dogXXX"), then it will work with a brand new object at (say) 200,000 leaving your dog1 at memory address 100,000 unchanged.
Apologies for the memory address abuse which will have experts spitting their coffee...
In java you're passing parameters by value to the methods, but the parameters are themselves ref type if the parameter is an object.
As a contrast in a programming language like C that passing by reference is allowed, if you print a reference you get something different from what you get when print it's value.
To insure that objects are reference types and compare them with primitives, Try this:
public class TestClass {
public static void main(String[] args) {
String s = new String("a");
String t = new String("a");
System.out.println(s==t);
char a = 'a';
char b = 'a';
System.out.println(a==b);
}
}
The result is :falsetrue
References in Java are passed by value of the reference.
When you pass reference as a method parameter copy is created and you operate on this copy.
To illustrate it have a look at this sample code:
final Person person = new Person();
person.setName("A");
changeName(person, "B");
System.out.println(person.getName());
Now if we have changeName implemented as this:
private static void changeName(Person person, String name) {
person.setName(name);
}
Then the result is B. It's because copy of the reference still points to the same object and there is possibility to modify it.
On the other hand if you change the changeName method to this:
private static void changeName(Person person, String name) {
person = new Person();
person.setName(name);
}
Then the result is A. It's because copy of the reference points to the new object, but original reference still points to the original object and it's value is not modified.
If Java would pass object references by reference than the result would be B, because it would operate on the original object.
When you pass an object as a parameter in Java, you actually pass a reference, and the reference is the value used in the stack. However, any assignment you make to this reference inside the method will not be observed by the caller, because you only change a copy of the reference. Same goes with primitive values as parameters.
In other languages (like C++), you have the option to pass by reference, allowing you to change the reference itself from within a method. In Java, for example, you can't implement a swap method that takes two parameters and swaps them. In C++ it's possible.
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 3 years ago.
I know a little bit about how Java is pass by value, and how passing a object to a method can change the object's field (ex. change1() in the Car class).
However, my question is why change2() and change3() don't change anything (especially change3())
public class question {
public static void main(String[] args)
{
Car c1 = new Car(1000,"Hyundai");
Car c2 = new Car(2000,"BMW");
c1.change3(c1);
c1.change3(c2);
System.out.println(c1.name + " "+ c1.price );
System.out.println(c2.name + " " + c2.price);
}
}
class Car
{
int price;
String name;
Car(int p , String n)
{
this.price=p;
this.name=n;
}
void change1(Car c)
{
c.price=0;
c.name="Changed";
}
void change2(Car c)
{
c = new Car(999,"Honda");
}
void change3(Car c)
{
c = new Car(888,"Audi");
c.price=80;
c.name="xxx";
}
}
Every time JVM executes new operator, a new Object/Instance is being created. You are creating a new object of the Car type in your change3(Car c) method and storing the reference on that object into local variable c. After this, anything you set on that c is amending new object, and not the one you passed a reference of.
void change3(Car c) //receives the reference to the object you pass;
{
c = new Car(888,"Audi"); //creates a new Car object and assigns reference to that **new object** to the variable c.
c.price=80; //here, you're changing the price/name fields of different object.
c.name="xxx";
}
Pay attention, that in change1(Car c) you do not create a new object, but in change2(Car c) and change3(Car c) - you do [explicitly] create new objects.
Edited:
Java is pass by value for primitives and for objects, it's a copy of the original reference.
To be more specific it's a copy of the same reference, which means that is a different pointer to the same reference of the same object, so if you change the object in your method, the original object is going to change too. BUT if you assign it again (with the new operator in your case) , you are going to update your pointer inside your method to a new reference, but the original pointer remains as it was.
Another about probably most upvoted question about Java on StackOverflow :)
The pass by value or reference probably comes from the understanding and conventions used in C++ language.
The types of parameters are passed by value.
But when passing an object it doesn't pass the whole object, but a copy of address in memory (aka reference) pointing to that object.
Passing parameter by reference means it's possible to change that parameter inside of an method and that change would be visible outside of that method.
Java in "passed by value" because changing/reassigning the passed parameter isn't visible outside of an method.
In the case of:
void change1(Car c)
{
c.price=0;
c.name="Changed";
}
The assignments to price and name are visible outside of that method, because the the method changes the member fields of the passed instance and not the instance itself.
The change2 and change3 methods doesn't reflect outside of them because of reassigning the passed c parameter.
When reassigning passed object, the address behind passed object parameter no longer points to the same object as originally passed one.
Similary, it's not possible to reflect the change or reassigning of passed primitive or:
void change4(String name) {
name = "whoopsie";
}
//and later calling it with:
c1.change4(c1.name);
Changing the inner state of an object isn't the same as changing the object itself.
Here is the code of the class i have written
class Demo
{
int x,y;
Demo(int a,int b){x=a;y=b;}
public void swap(Demo ref) // interchanges field values of x and y
{
int temp;
temp=ref.x;
ref.x=ref.y;
ref.y=temp;
}
public void change(Demo ref1,Demo ref2) // supposed to interchange to class variables of Demo class
{
Demo temp = ref1;
ref1 = ref2;
ref2 = temp;
}
}
swap method works fine i.e. interchange values of x and y.
Now, I have two questions here:
how the swap method is able to change the actual data passed to it? (I have read that their is no pass by reference in Java.)
why change method does not interchange class references?
Pass-by-value in Java is somewhat interesting. You're passing a reference to an object on the heap by value. So, by dereferencing/accessing ref you're accessing an existing object on the heap. That object's fields are changed, and any other references to that Demo instance will reflect these changed when dereferenced(as it's the same object).
Because references are passed by value, calling change(myDemo1, myDemo2) passes the values of the myDemo1 and myDemo2 references. We're not passing in a reference to the myDemo1 reference. Switching around the values won't affect them outside the method.
Let's just say that for simplification's sake the references are valued 12345 and 23456. For the first, we pass in a reference to 12345, and we then change things with that object. Any other dereferencing of 12345 will reflect those changes.
Now, let's try the following:
public static void main(String... args){
Demo d1,d2;
d1=new Demo(1,2); //VALUE of d1 is 12345, and deferencing d1 will get us a demo object at 12345 with 1 and 2.
d2=new Demo(9,8); //VALUE of d2 is 23456. Deference it, get a demo with 9 and 8.
change(d1,d2); //d1 and d2 are passed by VALUE. `change()` gets its own copy of d1 and d2 to play with.
}
I am trying to understand the difference between Object with primitive variables when using them as parameters in a method.
There are some examples using reference variables:
public class Test1 {
public static void main(String[] args) {
int[] value = {1};
modify(value);
System.out.println(value[0]);
}
public static void modify(int[] v) {
v[0] = 5;
}
}
result: 5
public class Test2 {
public static void main(String agrs[]) {
Integer j = new Integer(1);
refer(j);
System.out.println(j.intValue());
}
public static void refer(Integer i) {
i = new Integer(2);
System.out.println(i.intValue());
}
}
result: 2 | 1
So what is different in here?
In java array is primitive type.and Integer is Object type.
For primitives it is pass by value the actual value (e.g. 3)
For Objects you pass by value the reference to the object.
In first example,
you are changing value in array.
while in other example ,
you are changing reference of i to other memory location where object value is 2.
when returning back to main function, as you are not returning value. its reference scope limited to "refer" method only.
Recall that the array references are passed by value. The array itself is an object, and that's not passed at all (That means that if you pass an array as an argument, your'e actually passing its memory address location).
In modify() method, you're assigning 5 to the first place in the array, hence, changing the array's value. So when you print the result, you get: 5 because the value has been changed.
In the second case, you're creating a new Object of type Integer locally. i will have the same value when you exit the method refer(). Inside it you print 2, then you print i, which is 1 and hence change doesn't reflect.
v[0] = 5, is like saying Get 0th element of current v's reference and make it 5.
i = new Integer(2), is like saying change i to 2's Integer object reference
In one case you are changing the internal values via the reference and in latter you are changing the reference itself.
The difference here is that they are different.
In your first example you are passing the argument to another method, which is modifying one of its elements, which is visible at the caller. In the second case you are assigning the variable to a new value, which isn't visible at the caller, because Java has pass-by-value semantics.
NB 'Primary variable' has no meaning in Java.
I don't know what the word 'advance' in your title has to do with anything.
I read that Java does everything by call by value. I was wondering how to verify this fact? As far as I understand, in case of objects(not primitives) functions get its own copy of reference but points to same object. In that case, reference of that object in callee function and caller function should be different? How can I verify that? In other words, how to print the reference of the object.
System.out.println(object); //does this print reference i.e text following #
EDIT:
I understand that modifying object in callee function does change the value in caller function. I am interested in how to print the references of objects as in what property can I print on console that clearly shows me 2 different reference.
Java passes references by value. This means you'll get a copy of the reference, so once you dereference that you'll get to the same object in the heap as with the original reference.
But if Java was pass by reference:
public static void nullify(Object obj) {
obj = null;
}
public static void main(...) {
String x = "Hello";
nullify(x);
System.out.println(x);
}
The call to S.o.p. would print null if Java was pass by reference. But it isn't, so x is unchanged and you'll get Hello.
Assuming Class A property aa
A a= new A();
a.aa = 1;
// print a.aa here should be 1
method(a);
// here a.aa should be 2
Void method(A a) {
a.aa =2;
a = new A();
a.aa = 3;
}
So this shows reference was passed as value. When you change the object in the method it does not change the reference of caller.
I think the String Object#1ed3af is composed of the class name of your object and it's hashcode, separated by a #. This is a unique string, identifying it.
Read this topic to get a full explanation !
I have the following code
class sample
{
public void update(List l)
{
l = null;
}
public static void main (String[] args)
{
List m = new ArrayList();
m.add("suresh");
m.add("sankar");
new sample().update(m);
System.out.println(m);
}
}
The answer will be {["suresh,"sankar"]}. The m is a pointer to the arraylist object, it contains an memory address value (for ex consider 0xf34 ). when we pass m to update method ,the local variable l will be set to 0xf34 that points to arraylist object in memory .when we set null to this variable l , the memory address replaces the arraylist with null ,hence the variable m should also refer null.am i right.please help.
No, the compiler has it right. :)
The parameter l contains a reference to the ArrayList object assigned to m. l gets updated to null, and indeed any later use of lwithin the update() method would see it as null. But l is a separate variable that has scope only within that method -- it's not linked to m in any way (other than the fact that they originally contained references to the same object).
The key to understanding this is to remember that all objects are accessed indirectly via a reference. When an object is passed as an argument the method, the "value" actually being passed is a reference, and not the object itself.
When you null out the l parameter in the update method, you are setting that specific reference to null - the original reference m remains unchanged, and the object referred to by both references is also unchanged.
If you know C/C++, then this can be paraphrased as:
void update(List* l)
{
l = NULL; // set the pointer to null - the object (*list) is unmodified
}
void main()
{
List* m = ...;
update(m);
printf(m->values());
}
The pointer m is copied by value. The object pointed to (the list *m) is not altered in any way. The value of the pointer is copied from m to l. When l is set to NULL, that is a local change that only affects the value of the l pointer.
Here's an example where pass by reference involves a non-local change,
class NonLocalChange
{
public void change(int[] i) {
i[0] = 2;
i = null;
}
public static void main(String[] s) {
int[] m = new int[1];
m[1] = 3;
change(m);
System.out.println(i[0]);
}
}
The result printed is 2. This is because the change method changes the object referenced by l, and not just the reference itself.
Note that this doesn't throw a NullPointerException, even though l is assigned to null. As before, it's a reference, and so it's a local assignment to the value of that reference.
Your update method just sets the local l reference to null without changing anything about the passed-in object.
just imagine that you have a address (X for example) in your heap.
if you set m to refer to X as well as l to refer to X. we have two variable referring to same address, if you change one of them to null, the other one will remain as old value.
Lets say, new ArrayList() returns address 2000 in which the new ArrayList object is stored.
List m = new ArrayList():
lets say, m # 9999 = 2000, here let the number following '#' indicates the address at which 'm' is stored and the number following the '=' represents the value of 'm' (that would be an address as well since it is a reference type). So now 'm' at address 9999 holds 2000 which is the address of the newly created ArrayList object.
update(m):
Since Java is call-by-value always, it calls the update() method copying the value stored in m which is 2000. So now the parameter 'l' in update() definition holds the value 2000 (which is also the address of the previouly created ArrayList object). So we can say,
l # 8888 = 2000 ('l' at address 8888 holds the value 2000)
l = null:
So now, l # 8888 = null
System.out.println(m):
What is the value of m now? it is still 2000. The update() method didn't change the value of m. The method has just changed its local variable 'l' value. so 'm' still refers the previously created ArrayList object and is being printed.
No, you're not right. Java, as many other high level languages, employs call by sharing.
You could think of it like that: the reference to the actual argument is passed by value. Which means that within the called function, the reference initially points to the same value, thus any changes to the value itself are visible outside the scope of the called function, but any changes to the local reference are not. It is as if a copy of the address was passed.
Some additional reading for those interested.
objects and primitives
java+pass+by+value search