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.
Related
i want to make sure that my understanding is correct in static-polymorphism
please look at the code below
class a {
int x=0;
}
class b extends a {
int x=4;
}
public class main4 {
public static void main(String[] args) {
a f = new b();
System.out.println(f.x);
b ff = new b();
System.out.println(ff.x);
}
}
the output is
0
4
does that happened because the compiler looks at the declared type of the reference and upon that determines which x to print at compile time ??
(f is declared as type a, the compiler looks at f.x and decides it means a.x)??
& if so,is this called a static-polymorphism or hiding or what ??
thanks in advance
Polymorphism is like looking on the object via the key hole. You don't see the whole object but only that it's part which corresponds to the type of variable you have assigned a reference to the object to.
The object can be seen as different "shapes/forms" - it depends what the key hole you are looking through. But it is still the same object in computer's memory. The form you can see depends on the type of variable you have assigned the object to.
Polymorphism is a multi-form of seeing same object.
If you have object created by new b() - you'll see it as a b class representant when you assign this object to the variable of type b. And you'll see it as a a class representant when you assign it to the variable of type a.
But it is still the same object. And... you can cast it between variables:
f = (a)ff;
and you'll see that suddenly the same object is seen as an representative of a class (including visibility of x field belonging to the a class).
let's consider the following code:
public class Test {
private int a;
public Test(){
this.a = 1;
}
public static void main(String[] args) {
Test A = new Test();
Test B = A;
// TEST1
B.a = 0;
System.out.println(A); // prints 0
// TEST2
B = null;
System.out.println(A); // also prints 0
}
public String toString(){
return Integer.toString(this.a);
}
}
In TEST1, we modify B and then A is modified because B points to A.
I may understand why in TEST2 A doesn't become null, because B now points to null.
But the results of the two tests seem contradictory: why A doesn't become null ?
Thanks.
The variables A and B were both referencing the same object. B.a = 0 is altering that object. But when you reassign B = null, you're not altering the object. You're just altering the variable.
Test A = new Test();
The variable A points to an instance of type Test
Test B = A;
The variable B points to the same instance as variable A does.
B.a = 0;
The instance, variable B is pointing to (the same instance variable A points to), is changed.
B = null;
Variable B does not point to any instance anymore, while variable A still points to the same instance of type Test as before.
The main thing to understand is that variables A and B do hold a pointer to an instance of type Test. The instance of type Test is represented somewhere in memory and many variables may reference (point) to it.
The expression:
B.a = 0;
means: find the instance B is pointing at and modify its state in memory.
The expression:
B = null;
means: let B point to some other instance in memory (in your case to no instance at all). While the expression:
B = A;
means: let B point to the same instance in memory as A does point to.
By making object b null, you just cut the referance between the test object which resides in the heap and the B. The other referance between the test object and the A remains regardless of the other referances of the object unless you cut it or changed it.
regards
In Java variables are stored in the stack, while objects themselves are stored in the heap. Primitive type values are also stored in the stack, thus primitive type variables don't touch heap at all. But object variables on the stack contain heap addresses instead of values themselves. So by assigning null to B you change the B's (and only B's) value on the stack, but the heap value remains unchanged, and A's value on the stack remains unchanged, so A still references the same object in the heap allowing you to access its attributes and methods.
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.
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.
public class testtype
{
private int a;
private double b;
testtype(int a,double b)
{
this.a=a;
this.b=b;
}
public void maketoequal(testtype oo)
{
oo.a=this.a;
oo.b=this.b;
}
void trytoequal(int c)
{
c=this.a;
}
public static void main(String[] args)
{
testtype t1,t2;
t1=new testtype(10,15.0);
t2=new testtype(5,100.0);
t1.maketoequal(t2);
System.out.println("after the method is called:"+"\n"+"the value of a for t2 is:"+t2.a
+"\n"+"the value of b for t2 is :"+t2.b);
int c=50;
t1.trytoequal(c);
System.out.println("the value of c after the method be called is:"+c);
}
}
why the c is not changed?
Java passes parameters by value (so a copy of the value is made and used locally in the method).
For a primitive type -- c in your case --, the value is the value of c, so your using a copy of the value of c and you don't change c
For an object the value is the value of the reference so even if you pass it by value (copy it) it still references the same object and you can change the object using your copy of the reference...
Java is strictly pass-by-value
Because primitive parameters are passed by value to the method, and so the value you change is local to the method.
You probably want
c = thistest.getA()
where getA() returns the value of a.
In java, parameters are passed by value, not by reference, so what you are doing in "trytoequal" won't work.
See these explanations on java variables value: http://www.yoda.arachsys.com/java/passing.html
Primitive datatypes are passed by value and not by reference, meaning that the c you get in "trytoequal" is a variable whose scope is just within the method and its value is a copy of the method parameter.
The value of c in the method is changed, and then discarded.