This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
I have the following code:
public class PassReferenceByValue {
static void modify(String m)
{
m = "Else";
}
public static void main(String [] arg)
{
String actual = "Something";
modify(actual);
System.out.println(actual);
}
}
It will print Something.
I get that Java doesn't pass objects at all. Instead, it creates copy of the reference passed. If i understood correctly, when I call modify(actual) Java creates another reference to the same object. So, now we have two references that reference to the object actual. Now, through the second reference, we modify the object and the object should change. The object actual should change, because through the copied reference we have the same access to the object.
Can somebody explain me where I fail to understand the concept of passing references by value?
static void modify(String m)
{
m = "Else";
System.out.println(m);
}
If you do this m will print Else, it is only the local variable m what is getting assigned to a new value. value of actual in the main method is not getting changed here.
All "variables" in Java are references to address in a memory when the object resides.
So you have:
actual -> String("Something")
after method invocation you have
actual -> String("Something")
and
m -> String("Something")
You are just changing m -> String("Else")
bot not actual -> String("Something")
Where String("...") notation means object String with value "...".
Check this
Java's pass by value and pass by reference is nicely explained
Strings are immutable, but that's a different discussion
You are not modifying the "object" pointed by String reference actual. In the method modify() you are just overwriting the reference to point to a new String object called "Else". Now this doesn't make any "effect" to the object pointed by actual. Hence when you print actual, it still remains the same
Why I am trying to make point 1 is, say your modify method was like below
public void modify(String s) {
s.replaceAll("Some", "Many");
}
Still the actual would have printed "Something" because of String's immutable behavior.
You're changing m which is a local variable only visible within modify() referencing an object. You're creating a new String object with the value "Else" and making m point towards it.
When you then come out of modify() and print actual, it is still a reference to the String object containing the text "Something".
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 months ago.
I'm Ryan who's a rookie in programming. I was going through the OOP part of my textbook today and I found a part that I won't understand at all. There are 2 codes, I'll have them copied here.
The first one is :
public class Change {
public static void main(String[] args) {
int x = 17;
dontChange(x);
System.out.println(x);
}
static void dontChange(int z) {
z = 42;
}
}
When the code was executed. The output would still be 17, which is not the expected 42(in my understanding of parameter and Method.)
The textbook provided another example as well, which results in a change.
public class Change {
void change(Student s) {//student is a type
s.name = "Fred";
public static void main(String[] args) {
stu.name = "Jane";
change(stu);
System.out.println(stu.name);
}
}
This code would result in the output the name as 'Fred', I was wondering where's the difference between them and what was the reason behind these codes when they look similar and worked totally differently.
Thank you for going through the whole post, I wish you have a great day!
You need to distinguish between “passing by value” and “passing by reference”. Maybe this helps
If you want to understand the answer to this Question, why the value does not change, you have to understand, why the value sometimes change.
The values changes,if the Datatyp is referencial. This means, that the data is stored at the heap(a part of memory) and our variable only points to this data. This means, that your variable only stores, where the data is really stored.
If we change our data,we are following our reference and change it there.
This means, that every reference, which points at our data is also changed. It is the same object.
What happens here is different. You are not dealing with referencial Datatyps.
You are dealing with primitives(int, float, char....). Those datatyps aren't stored in the heap. They are stored in the stack(another part of memory). This means, that the data is really stored in our variable. So, if we change our data in our variable, we aren't following an reference and change it there. We are really changing the value in our variable.
An analogy:
Referencial types are like notes, which point to a different note. In the second note is the data. If we try to change the datanote, we take a look at our first note with the reference to the datanote and then change the datanote. Any note pointing to the datanote has now the updated data.
primitives are like, if our first note has all the data. There is no pointing to somewhere else. It is our data
Primitives start most of the time with a lower case letter. Primitives can't have any functions or anything.
Refercal start most of the time with a Capital letter. They can have functions and are most of the time classes
What you wanted to do was to return the new value and set it equal to x.
I hope, i've helped you a bit.
If you have any Questions left, feel free to ask
sorry for my English:)
Firstly, I would point out the difference between the two examples you've shown. The method Change#change(Student)
public class Change {
public void change(Student s) {
s.name = "Fred";
}
}
Compared to Change#dontChange(int)
public class Change {
public void dontChange(int i) {
i = 42;
}
}
The most notable difference between these two methods is where they assign (=) the value they're passing. s.name vs i. Note the presence of the dot operator (.) indicating that there's access of an Object's field or method. This can help start the explanation of why change(Student) updates the value it assigns to as compared to dontChange(int).
There was reference of looking into the difference between pass-by-value and pass-by-reference in other answers, and that will be required information for WHY this happens. However, I think there should be a slightly deeper understanding of what a variable is in java for that to help explain it. The easiest explanation I find is that a variable in java is a number. Period. Always. Now that might seem weird, right? You obviously have an object when you do Student stu = new Student(), but that's only partially correct. You do instantiate (create/construct) an object, but the value stored in Student stu can actually be thought of as a number pointing to a spot in memory where stu's values are stored. There IS a difference in how these number are handled, but they are, in essence, all numbers.
Knowing this, you can work with the thought that values passed to a method in java are always passed-by-value. If you wanted to test this you could see the output of changing the body of Change#change(Student) to
public class Change {
void change(Student s) {
Student newStudent = new Student();
newStudent.name = "Fred";
s = newStudent;
}
}
You may expect the output name to still be "Fred", but it should result in "Jane". We didn't modify the object that Student s refers to, we updated what the variable s points to. The difference being that in the original Change#change(Student) method you assigned the value "Fred" to the name field (s.name) of the object that Student s refers to.
When you call Change#change(Student) with the variable stu the parameter s's value becomes the same identifying number that stu points to, but the variables themselves are entirely different. They only, when s is initialized, have the same value (a number pointing to a space in memory).
It should be noted that assigning "Jane" and "Fred" to the Student's name field is actually assigning a reference to a String which represents "Jane" or "Fred" to the Student's name field. As the name field's type is, assumed to be, String which is not a primitive type. Meaning it's a reference to some String object in memory.
What is happening here is passing by value and passing by reference. In Java all primitive types(int, char...) are passed by value to any method, this means the value of them are copied for the method to use.
Anything else like objects from classes you create are passed by reference. This means the contents of the object are not copied but the address of where that object is in memory is copied to the method. The value at this address(the original object) is then used within the method meaning changes to it are seen outside of the method.
To go into more detail and why this happens can get quite confusing as a beginner but other people have linked good articles to read. To put it simply in my own words.
Whenever you are using an object(non-primitive type) i.e Student. Java is actually seeing this as an address to that object but to keep things easier for the programmer Java doesn't make you declare this in any way. Any access to this object is automatically handled by Java to mean the value of the address you are using.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
I am confused about how Java deals with aggregation within objects, and in particular referencing of objects. It seems like objects will keep a reference to an aggregated object when it is passed as a parameter, rather than copying it like I've been lead to believe.
Say I have a basic class called Foo which contains a string attribute, print function, and setter for the text attribute.
public class Foo {
private String text;
public Foo(String text) {
this.text = text;
}
public void print() {
System.out.println(text);
}
public void setText(String text) {
this.text = text;
}
}
And a class called Bar which contains an attribute of type Foo, and a method called print which calls foos print method.
public class Bar {
private Foo foo;
public Bar(Foo foo) {
this.foo = foo;
}
public void print() {
this.foo.print();
}
}
If I define an instance of Foo, pass it into a new instance of Bar, and then call bars print method it will print "hello" as I expected. However if I then set the text of the original instance of foo to "Edited" using its setter method, bars print method will also print "Edited".
public static void main(String[] args){
Foo foo = new Foo("Hello");
Bar bar = new Bar(foo);
bar.print();
foo.setText("Edited");
bar.print();
}
Console Output
The Bar object appears to be keeping a reference to the Foo object even though I passed it as a parameter. I'm sure I am missing something trivial here, and I just wanted someone to explain this clearly.
"I'm sure I am missing something trivial here"
Not really. What you see is not a bug, it is a feature. Passing objects around in java means passing around references to them. Objects aren't "cloned" unless the code explicitly requests this through .clone(). Searching on this site for "is java pass-by-value or pass-by-reference" should help you find all the detailed explanation you need.
Reference copied, not object
It seems like objects will keep a reference to an aggregated object when it is passed as a parameter, rather than copying it like I've been lead to believe.
No, the object is not copied.
The reference (pointer) is copied when passed as an argument to a method. The object (the referent, the thing to which the pointer points) is not copied.
The pointer is really an address in memory someplace (though not seen as such by us Java programmers). That address, basically a number, is being copied when passed into the other method. But the object is left untouched, unaware of any references.
Here's a diagram of several Cat objects in memory. Three of the five are candidates for garbage-collection because they have no references remaining, no pointers pointing to them. At first Lilly Mae cat has one pointer pointing to it.
Cat c = new Cat( "Lilly Mae" ) ;
The c variable is not holding a Cat, it holds the address elsewhere in memory where you can find the Cat object. Think of that line as saying:
variable-holding-pointer-that-can-only-point-to-objects-of-class-Cat c = instantiate-new-object-of-type-Cat-and-return-a-pointer-to-its-location-in-memory( "Lilly Mae" ) ;
Then we pass that pointer as a argument to another method.
Human h = SubservientHumanLocator.findFirstAvailable() ;
h.feedCat( c ) ; // Passing a copy of the address of Lilly Mae to this other object’s method.
After the reference to the Cat is passed to the Human, we still have only one hungry cat. We did not clone the cat. We now have two references, both pointing to same original Cat object.
Here is a diagram of state before and after the Human::feedCat call.
After calling on the human to feed the cat, the variable c may fall out of scope. After feeding the cat, the Human object h will likely let its copied reference also fall out of scope. Then, if no other references had been made, and with no existing references remaining, our well-fed Cat object will become a candidate for garbage-collection.
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.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
If I instantiate an object and pass it to an function, in this function I assign this object to null.
It seems when return from the function, the object still there.
I just want to know when I assign null, what happens.
You can never assign to an object. All you ever have are primitives and references. A reference is either null or a pointer to an object of suitable class.
Java arguments are passed by value. Your called method got a copy of a reference. It made that reference null. The calling method has its own reference which was unaffected by any assignments to the passed copy. That reference still points to the object.
Arguments to methods in Java are 'pass-by-value', which means you are passing a copy of the object reference into the method. Assigning this reference a value of null will change its value within the method call, but does nothing to the reference outside the method, since its a copy. Illustrated with code:
void doSomething(final String input) {
input = null;
System.out.println("Input is: " + input); // prints null
return;
}
final String name = "Bob";
doSomething(name);
System.out.println("Name is: " + name); // prints 'Bob'
when you instantiate an object and pass it to a function, and inside the function you reassign that to null or whatever, at the calling side it is not reflected as arguments are pass by value (copy of reference in case of objects), at calling side it'll still point to the old object. If you want to restrict reassigning in a method, you can use final keyword in method parameter
When you pass the object reference to a function(Java always call it method),in the method scope,a new reference is created on stack memory,but they point to the same object in heap memory.So if you assign null to the new reference,Only this reference's link to that object is break,It does not affect the prevous one.
I can't understand why the overloaded function 'increase' does not change Integer but does change Point.
The propuse of 'Integer' class is to wrap int so it will be a reference Type.
import java.awt.Point;
public class test2 {
public static void main(String[] args) {
///1
Integer i = new Integer(0);
increase(i);
System.out.println(i);
///2
Point p = new Point(0,0);
increase(p);
System.out.println(p);
}
public static void increase(Integer i){
i = 1;
}
public static void increase(Point p){
p.setLocation(1, 1);
}
}
the output is :
0
java.awt.Point[x=1,y=1]
Also, is their a simple way to pass a variable to a function by reference in Java?
Integer class is an immutable class, that means its content can't be changed after it's created.
Also, Java is pass-by-value so the variable i is passed by value, and the fact that it changes inside the function has no effect on the caller.
Read here: http://en.wikipedia.org/wiki/Immutable_object for more information on immutable objects.
The simple answer is that Java uses pass by value, not pass by reference.
In the Point case, the method is changing a field of the point object whose reference was passed into the method.
In the Integer case, the method is simply assigning a new value to the local variable i. This does not update the variable i in the calling method, because Java uses pass by reference.
The other issue is that Integer has no setValue methods because it is immutable. If you want to do the equivalent of what the Point version of the method is doing, you will have to define an IntegerHolder class that has both a getter and a setter, together with methods such as increase, that your application needs. (Alternatively, find such a class in a 3rd party library.)
Integer objects are immutable, i.e. you can't change them. If you could, the syntax would be like
i.setValue(1);
If you want to pass a non-object by reference, you can either wrap it in an array of length 1 or (better) create a trivial wrapper. However, there is little reason to do so - don't port your code from C 1:1. Usually, you should have a semantically loaded object, like an Account on which you can call the increase and decrease (or maybe just setBalance) methods.
In this function:
public static void increase(Integer i){
i = 1;
}
autoboxing makes this equivalent to:
public static void increase(Integer i){
i = new Integer(1);
}
i.e. it changes the reference that i contains, not the value that it contains. The Integer object is itself immutable, there's actually no way to change the value of one after it has been created.
Since that reference is a local variable, any changes to it will not affect the variable that was passed in.
When you write i = 1, you are changing the i parameter to point to a new boxed Integer instance.
The original Integer instance that you passed to the function is not—and cannot be—changed—Integers are immutable
Answer here: http://www.javaworld.com/javaworld/javaqa/2000-06/01-qa-0602-immutable.html
This reference could be useful: http://javadude.com/articles/passbyvalue.htm
If you wanted the two methods to be equivalent, the second one would look like this:
public static void increase(Point p){
p = new Point(1, 1);
}
And then you would see that it outputs the original point here, too.
There is no pass a variable to a function by reference in Java.
You can simulate it by passing an object which contains the variable (like you did in your increase(Point) method) - you'll have to be sure to assign to the variable, though, not to the object containing the variable.
As said before, there are several "mutable wrappers" around (for example org.omg.CORBA.IntHolder and java.util.concurrent.AtomicInteger in the standard API), but it is not difficult to create your own, and in most cases it would be better to use a sensible "Business object" like an "Account" instead.