In the following image, p points to person.
p is passed as a reference to a function named callFunction. Now,if I make any change in p will they also get reflected in person ? Please explain.
I understand that argument passed is the reference value of the original variable (I hope so !). But I can't think further.
If you change the details of p as such, it'll get reflected
// Nothing done to p before this
p.changeName("Not Sanika Anymore"); // This will be reflected as both point to the same object as references are the same
If you create a new Person and assign it to p then it wont
// New Person for p
p = new Person("New Sanika"); // now this p is pointing to the newly created object's reference
p.changeName("Not Sanika Anymore"); // This won't be reflected
That is because java is purely pass-by-value. You are passing the reference of the object as a value to callFunction().
This answer by Eng.Fouad explains this concept in a really good way.
Yes, because both reference are pointing to same Person object. When you change some attribute using any reference, same object will be updated.
As long as you change the members of the object which is pointed by the reference p , They'll get reflected , As java passes parameter by value .
What is Pass by value ??
The actual parameter (or argument expression) is fully evaluated and the resulting value is copied into a location being used to hold the formal parameter's value during method/function execution. That location is typically a chunk of memory on the run-time stack for the application (which is how Java handles it), but other languages could choose parameter storage differently. So there is no way of the method having contact with the original reference here.
So Pass by reference is implemented differently , this is where actually you can have freedom of playing with reference . Here references can be changed in the method .
Related
This question already has answers here:
How do I copy an object in Java?
(23 answers)
Closed 8 years ago.
This might have been asked already but since I am not so sure how to phrase it I could not find it.
Essentially
Suppose we have the class a, (see code below), and we want to copy an instance of it, a1, to another instance a2.
So, in my main I would have a1.copy(a2)
I know that using copy2 method this will work. However copy1 will not. I just would like to clarify why this is. Is it because the parameter is just a "copy" of the object, so the object itself (a2) is not altered.
class a {
private int val;
public class(int val){
this.val = val;
}
public void copy1(a obj){
obj = this;
}
public void copy2(a obj) {
obj.val = this.val;
}
}
The key to understand your problem is that Java's method call is always pass-by-value, not by reference.
When you call a.copy1(b), Java copies a value of b's reference(say it is called b_copy, please note that b_copy points to the same memory location as b), and then pass b_copy to the method copy1.
And in your method of copy1, Java only changes the reference of b_copy.
public void copy1(b_copy){
b_copy=a;
}
So now :
b_copy: b_copy=a;
b: b does not change at all;
When the method ends,b_copy dies. So nothing changes on b!
While a.copy2(b) manipulates on the object itself, but it still copies a new value of b(say b_copy again) and pass into copy2
public void copy2(b_copy){
b_copy.val = a.val;
}
Since b_copy points to the same memory of b, so when you do changes on b_copy.val, you also does the same on b.val itself. That's the reason why b changes.
So now :
b_copy: b_copy, but b_copy's val changes
b: b's val also changes, since b_copy is points to the b's memory location;
And then when method ends, b_copy dies, and b has changed!
You may find more discussion on Is Java "pass-by-reference" or "pass-by-value"?
And you may also need How do I copy an object in Java?
When you call the method copy1(), the parameter is a copy of the reference of the object a obj. When you set it to this (obj = this;) the copy of the reference of the object is replaced by the current object, but the original object and the reference to the object at the place you are calling the copy1() method stays the same. You just change the copy of the reference of the object.
When you call the method copy2(), no reference work is done there, and you are doing one by one matching of the variables (properties of the objects) and there is no copy of reference work there. You are changing the object itself. In this case, this.val = obj.val; would also work.
For more understanding, check this topic and check how other languages like C or C++ handle parameter passing issue.
I think you might want to look into how parameters are passed in Java.
For primitive variables, they are passed by value. If I recall correctly, this means that a temporary value is passed and any changes to the variable in the function update only the temporary variable.
However, objects are passed by reference. This means that instead of the entire object, essentially a pointer to where the object is in memory is passed.
What this means is that updating an object's variables produces lasting effects on that object. Additionally, if you set one object equal to another object, you're really just setting the memory references to be the same (a byproduct of this is that the values of the variables in the objects are then linked).
This explains why the first function fails to do what you want (you're setting the memory locations to be the same). And the second succeeds (you're performing a deep copy into a new memory address).
Your reasoning is correct. When you pass an object to a method (as you do in copy1), all you are doing is creating another reference to the same object. If you override this reference, as copy1 does, it just means that that reference now points to a different object - it does not, and can not, change the original object.
Lets get the terminology straight once and for all. I have been confused about all the conflicting vocabulary online relating to passing by reference and value.
Below is an easy clean example of passing an object argument to a method.
The result is that Mike Grant's name is butchered as well as his age. So the underlying object was changed.
2 Major questions:
What is the value, and what is the reference?
Would the hashcode be different of p1 once the changePersonObject() method is run on it?
My code:
public class App {
public void changePersonObject(Person p){
p.setAge(100);
p.setFirstName("Lost");
p.setLastName("Boy");
}
public static void main(String[] args) {
App a = new App();
Person p1 = new Person("Mike", "Grant", 24, 180);
a.changePersonObject(p1);
System.out.println(p1); // person objects name is changed to "Lost"
}
}
Java is pass-by-value indeed, but actually the one that hold this value is little bit of different with what you might think of. java is pass by value?
the word value, which in basic data type is the data itself, for instance
int numberA=100 ;
int numberB=numberA;
the value that passed from numberA to numberB is the data 100.
things never change in Reference type:
Person p = new Person("Lost", "Boy", 24);
Person person=p;
person=new Person("Rugal", "Bernstein", 23);
the value that is passed from p to person is the reference address that point to the Person("Lost", "Boy", 24) one, for any details please execute program above and debug it yourself to clarify them.
Here you might think, after person=new Person("Rugal", "Bernstein", 23); the value of person now is disparate with its original one. yes of course, now if you println(person) and that will turn out to be a new Person as you might think of.
But what about p, does that changed because Java is pass-by-value?
Actually, after test with that, I found it is not, even if you changed the person, it will not bother p. what's wrong with java, is there any problem here ?
Yes, java demonstrated there is no pointer in it and all the things that passed in parameter is called reference. lets go back to C/C++ style of programming:
int data=100,temp=50;
int* pdata=&data;
int& rdata=data;
pdata=&temp;
println("%d %d",*pdata,rdata);
rdata=temp;
println("%d %d",*pdata,rdata);
anything special can you find from above?
yes, actually in C/C++ , there is two type of so call pass-by-value method, the first one declared by * is called pointer, second one start with & named reference, here please do not consider this reference with java, because you will find they are different later.
in C/C++ , the reference is a kind of alias, in other word, these two variables are totally identical thing, whatever changes you made on one will thus effect the other one. because they are just one thing.
But Pointer is a little different with reference. yes pointer can also point to a variable and you can also change the value of that variable by using *pdata=temp. But here is a problem, when you using pdata=&temp to change the pointer itself, will the data change according to pdata?
the answer is NO!
you can test it yourself ! because what value store in pointer is the address of data variable, when you want to change the value of data it can surely change it by refer *, but when you try to change the address that stored in pdata it would not bother with data because they are totally different two variable.
Now do you have a familiar sense that you have ever feel this before?
yes, in java the so called reference is what pointer behave like in C/C++.
and here we have the deal, in java that demonstrated itself with pass-by-value is correct and no more pointer is a mendacity.
now let me answer questions:
1.the word value is the data that stored in memory. in java primitive type hold real data as value and address as value in reference type.
2.as I have already explained above, you can test it yourself!
3.and I tested some code, the hashcode() will not change so long as the value of your object do not change.
for instance:
Person p = new Person("Lost", "Boy", 24);//Hash Code 38443066
p.setAge(100); //Hash Code 38443066
p=new Person("Rugal", "Bernstein", 23);//Hash Code 38444526
because in default situation, hashcode() method only measure the address itself hence so long as your address unchanged, the hashcode() will not change.
you can override this method by yourself to measure its member fields as well.
the method changePersonObject() only changed the member field in it thus will have no difference with outer hashcode(). you can achieve it by person=new Person("Rugal", "Bernstein", 23); in this method, its hashcode() will surely changed.
please try it and you will get more comprehension with Java
The expression
Person p1 = new Person("Mike", "Grant", 24, 180);
creates a new object of type Person and assigns the value of its reference to the variable p1.
Java is pass by value. That means that a copy of the value used as an argument is bound to the parameter of the method.
The expression
a.changePersonObject(p1);
is passing p1 as an argument to the invocation of the changePersonObject method. A copy of the value of p1 which is the reference to an object is therefore bound to the parameter p in
public void changePersonObject(Person p){
p.setAge(100);
p.setFirstName("Lost");
p.setLastName("Boy");
}
In the method itself, p is referencing the same object as p1 in main. So when you dereference it by invoking a method such as
p.setAge(100);
you're affecting the same object.
If instead you did
p = new Person("Soto", "Deli", 24, 42);// whatever arguments
The variable p now has a new value, the value of the reference to a new Person object. This will not affect p1 in main in any way.
would the hashcode be different of p1 once the changePersonObject()
method is run on it?
If you haven't implemented a hashcode method in Person, then the value returned will be the same regardless of you changing the value of the instance's fields.
Java only supports pass by value, not pass by reference. (References to objects are passed by value). For more information please see the following: http://javachannel.net/wiki/pmwiki.php/FAQ/PassingVariables, http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html, and http://javadude.com/articles/passbyvalue.htm?repost
p1 = new Person("Mike", "Grant", 24, 180); <-- the "value" of the Object person is the Object, p1 is the "reference" to that Person object
Yes. If Person implements hashCode() correctly.
The problem is that when comparing with other languages, the meaning of pass by value and pass by value is slightly different.
In your example, the fact that you can change the values of p1 in a method may make you believe that you are passing by reference - this is not the case in Java.
To illustrate, that this is passing by value
public class App {
public void changePersonObject(Person p){
p = new Person("Lost", "Boy", 24, 100);
}
public static void main(String[] args) {
App a = new App();
Person p1 = new Person("Mike", "Grant", 24, 180);
a.changePersonObject(p1);
System.out.println(p1); // person objects name is still "Mike"
}
}
Unless we can see how the hashcode is generated, then it is impossible to answer the second question. If it is not implemented in Person, then it is likely that the value returned will be the same regardless of you changing the value of the instance's fields.
I came across something that I could not comprehend and never realized it could be done.
I was playing around with this block of code in Android, and what intrigued me was this:
public boolean onTouch(View v, MotionEvent event){
Rect outRect = new Rect();
_btn.getHitRect(outRect);
// ... rest of code cut
// outRect fields of that Rect object is 'filled' in.
}
How is it that Android's Java can directly modify a Rect object outRect which was passed into the method in order to obtain the Rect of a button widget.
That surprised me, as I thought there was no such thing as 'pass by reference' in Java, in Java parlance, using a 'call-by-reference' rather, its 'pass by value' or 'call-by-value'?
Yes, I have read this question asked before but am stumped, or is that an Android thing?
Can anyone shed some light on this?
The address, in the case of the objects, is a value, the value is copied, analogous to the primitive values. But it's a value which points to an object, and the object is not copied. It exists only once in memory and can be manipulated.
The outRect reference is passed to the getHitRect method, which then modifies the object referred to by outRect. References are passed by value.
For a detailed explanation of this, read this article: http://javadude.com/articles/passbyvalue.htm
The reference to the Rect object is passed by value but the Rect object itself is allocated on the heap so it can be updated. In effect, this gives you pass-by-reference semantics. However, you cannot change the reference; in other words, something like this won't work:
public void someFunction(Rect r) {
r = new Rect(); // will not be seen by the calling function
}
The highest-rated answer to the question you linked to explains this pretty clearly:
Java is always pass-by-value. The difficult thing can be to understand that Java passes objects as references passed by value.
It then goes on to show two examples that leave no mystery in the behavior you're asking about, unless I've misunderstood what's surprised you.
All parameters to methods in Java are passed by value, both primitives and objects. However, the way objects are referenced in Java is closer to that a C++ pointer than a value. For instance, consider that any object value in Java may take the value null, but in C++ only pointers make take the value null (whereas objects and references* are always valid initialised values).
But what does pass-by-value for an object value actually mean? It means to create a copy of an object and push it onto the stack for the called method to use. Whereas for a pointer it means to push the pointer value onto the stack. That way both the calling and the called method have access to the same memory location where the object value is stored. Thus any changes performed in the called method will be reflected in the calling method.
* There are some instances where a reference may contain corrupt data.
So I have an algorithm that forces me to pass in an object as a parameter recursively and on different depths of the recursion it sets the values of the object. The problem is Java isn't allowing me to do this because they pass in by value or something else that is just messing me up. How can you make sure that the object passed in retains the value set?
You never pass an object as an argument in Java. You either pass a reference or a primitive value. The argument is always passed by value. Java doesn't have pass-by-reference at all.
If you're passing in a reference to an object, and you want to make sure the code you call doesn't change the data within that object, your options are:
Create a copy and pass in a reference to that instead
Make your type immutable in the first place.
EDIT: Just to make it clear, if you have:
Foo f = new Foo();
then the value of f is not a Foo object. It's a reference to a Foo object. If you now call:
doSomething(f);
then the value of f is copied as the original value of the parameter within doSomething. That behaviour is basically the definition of pass-by-value. There's nothing doSomething can to do change the value of f - it will still refer to the same object afterwards. The data within that object may have changed, but it won't be a different object.
In a real-world analogy: if I give you a copy of my address, you can go and paint the front door, but you can't change where I live.
As Jon states, all non-primitives are passed by passing a copy of the reference. You don't have a choice. So your recursive method should be able to update the object if it is mutable. HOWEVER, you can't reassign a reference and expect it to propagate back up the call stack. And remember that Strings are not mutable.
In other words, if you do the following, you have not changed the object that was passed:
void myMethod(Object o){
o = new Object();
}
The above changes the local reference to o but does not change the caller's reference to o. If you need to do something like this you would need to return o.
Why doesn't this change the initial object:
public class Foo
{
Bar item = new Item(5);
public changeBar(Bar test){
test = new Item(4);
}
public run(){
changeBar(item);
}
}
In this case item doesn't get changed. How is this possible? I mean, you're passing the reference as parameter in the method, so I'd say assigning a new value to it, means the initial item would also be changed.
Can someone explain to me how this works.
=======================================
however, my question is the following:
the following does work right?
public changeBar2(Bar test){
test.parameter = "newValue";
}
I don't see how that's different.
Consider a thought experiment:
changeBar(null);
Would your code above change the value of null?
The answer to your question is that although your Bar object is passed "by reference", this is different from passing the reference itself by value. In Java, all parameters are passed by value, even when they are themselves references to other objects.
public changeBar(Bar test){
test = new Item(4);
}
changeBar(item);
Here the value in item in copied to test. So as of now, both item, test are pointing to same object(s). Inside the method, test is pointing to a different location which doesn't affect the item. You are passing by value and not by reference.
public changeBar2(Bar test){
test.parameter = "newValue";
}
The above modifies the object that is passed because both the test and item are referring to the same object.
So, test can totally either point to a new object or modify the object was earlier referring to. Both are different and are valid.
Parameters in Java are ALWAYS passed-by-value.
At the beginnning of function changeBar() test is a reference to item, but then you overwrite it with a reference to a newly created item. You therefore only overwrite the local variable with a different reference, but don't change the referenced by object.
test in changeBar is basically as pointer. So when you assign it, you are changing the pointer.
Here is an article: http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
You are giving the method the reference to this object, that is, its address so to speak. So this address is stocked in a variable named test.
Then your method erases what is written in the test variable, and writes instead the address of a new Item object it created. Nothing here changes anything to the initial Item object, nor to the references to it that are outside the method's scope.
I guess I am pretty approximative here and I will be glad to get corrected.