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
Related
I have the following code. I can't, however, understand it's behavior about pass by value and reference.
class Dog{
String name;
int x=100;
Dog(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
class Demo{
public static void main( String[] args ){
Dog aDog = new Dog("Tom");
foo(aDog);
if (aDog.getName().equals("Tom")) { //true
System.out.println( "Java passes by value."+ aDog.getName());
System.out.println( aDog.x);
} else if (aDog.getName().equals("Taz")) {
System.out.println( "Java passes by reference." );
}
}
public static void foo(Dog d) {
++d.x;
d = new Dog("Taz");
++d.x;
}
}
This will provide output as
Java passes by value.Tom
101
Why is the output 101? I was expecting output 102.
You're incrementing x twice, but on different dogs. Look at this code:
public static void foo(Dog d) {
++d.x;
d = new Dog("Taz");
++d.x;
}
Initially, d refers to the dog with a name of Tom, with x=100. That isn't a copy of the original object - it's a reference to the same object. Java passes the reference by value, which isn't the same as either passing an object by value or passing an object by reference. It's important to understand that the value of aDog in main isn't a Dog object - it's a reference to a Dog object. The value of that reference is passed, by value, to your foo method... so the initial value of d is the same as the value of aDog. Further changes to the d variable itself (rather than the object its value refers to) do not change the aDog variable.
So, looking at the rest of foo:
After the ++d.x, d refers to the dog with a name of Tom, with x=101.
After d = new Dog("Taz"), d refers to a dog with a name of Taz, with x=100.
After the ++d.x, d refers to the dog with a name of Taz, with x=101.
The calling code only ever knows about the dog with a name of Tom, so it prints out Tom 101.
You increment x once, on the dog that was given to the method ("Tom").
Then you create a new dog, called Taz.
You then increment x for that second dog. It won't affect the original one, and both dogs will be at 101.
As for why the calling method still refers to "Tom", even though you changed your local variable to point at "Taz": That's because a local variable is just that: local to the place it is used. The caller does not care about what you do with it later, its own variable will still point at "Tom".
Because Java does not support pass-by-reference or "out parameters", there is nothing the called function can do to change the value of variables in the calling function.
But note that objects are not stored in variables. Only a pointer to them is stored there. The actual object instance itself is in a shared location (the program heap memory). So the called method can indeed change the object. But it cannot assign a different object into the calling function.
Takeaway: Make your local variables final, especially method parameters. Then you cannot reuse the same variable for two different things, and the code becomes less confusing.
Java is always Pass By Value:
main():
Dog aDog = new Dog("Tom"); // {name="Tom", x=100}
foo():
++d.x; // {name="Tom", x=101}
d = new Dog("Taz"); // {name="Taz", x=100}
++d.x; // {name="Taz", x=101}
However, you can get entirely new copy but you need to return it.
In main(): update this line
foo(aDog);
to
aDog = foo(aDog);
also update foo() as:
public static Dog foo(Dog d) {
...
return d;
}
When you use the new keyword like this d = new Dog("Taz");
You create a new Dog, the new Dog it's called Taz and have x=101, so you don't increment d.x 2 times for the same Dog
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.
In the following code why output is 0 42 42 rather than 0 0 42.
In Java object is not passed by reference so why value of t.x was modified to 42?
class Two
{
byte x;
}
class PassO
{
public static void main(String [] args)
{
PassO p = new PassO();
p.start();
}
void start()
{
Two t = new Two();
System.out.print(t.x + " ");
Two t2 = fix(t);
System.out.println(t.x + " " + t2.x);
}
Two fix(Two tt)
{
tt.x = 42;
return tt;
}
}
Because what's being passed around in Java is the value of the pointer to the object. Thus when you do tt.x=42, you are changing the original t.x to have a value of 42. And when you return tt you are actually returning the same pointer, so infact t and t2 point to the same instance of the object.
In Java object is not passed by reference so why value of t is
modified to 42?
The value of t is not modified to 42. t.x is modified to 42.
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.
Yes it is passed by value. The value is the reference. t is a pointer to a new Two(). You pass the value that t is referring too and point to it with tt.
Your method fix is not really testing passed by value adherence. If you were really testing for passed by value adherence the method should be something like below:
Two fix(Two tt)
{
// Create a brand new instance of Two
Two newTwo = new Two();
newTwo.x = 42;
// Assign the new reference to the passed in value.
tt = newTwo;
return tt;
}
In your original fix method you are just mutating the passed in object.
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.
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.