Reputation: 910
I have a Long object in a class, I give it a value and then I pass it to another class' constructor, where it is changed. Why are the changes NOT visible in the first object?
The code:
public class ClassA {
private Long t;
public ClassA() {
t = new Long(10);
System.out.println(t); // prints 10
new ClassB(t); // it is modified (see ClassB)
System.out.println(t); // prints 10 again
}
public static void main(String[] args) {
new ClassA();
}
}
class ClassB {
private Long p;
public ClassB(Long p) {
this.p = p;
this.p = this.p + 1;
System.out.println(this.p); // prints 11
}
}
The output is: 10 11 10 The Long variable is initialized in ClassA. Then I pass it to ClassB, modify it and clearly the changes are not visible in the first class. Why?
Upvotes: 0
Views: 166
Reputation: 121840
It is because the Long
class is immutable; once an instance is created, it can never change.
In this line:
this.p = this.p + 1;
what you are doing is create a new Long
object. Other examples of immutable classes include all "wrapper" classes for primitive numeric types (Byte
, Short
etc) and String
.
What doesn't help is that it makes the +
operator unintuitive; what really does not help is that the language allows +
on all of these immutable classes.
What happens in the above line could be written as (although it happens differently in the bytecode, I suspect):
long tmp = this.p.longValue();
tmp += 1;
this.p = new Long(tmp);
You can also verify immutability by marking your p
as final
in class B
, which means the reference p
can never change; this.p = this.p + 1
will raise a compile error since you attempt to modify reference p
.
Upvotes: 6
Reputation: 17236
this line this.p = this.p + 1;
does not modify p, it creates a new Long
from adding the two values p
and 1
and then sets this.p
to be a reference to this new Long
. Objects of the class Long
do not have mutator methods so they can never change (within Class B this.p
was not changed, this.p
became a reference to a new Long)
So the behaviour is actually
this.p=p;
Long newLong=this.p + 1;
this.p=newLong;
What you're imagining is
this.p=p
this.p.imaginaryAddLocal(1);
this would effect the original p, but of course this method imaginaryAllLocal
doesn't exist because objects of the class Long are immutable
Upvotes: 2
Reputation: 169
1- You are just modifying the p member of class B
2- Everything is passed by value (and not by reference) in Java
Upvotes: 0
Reputation: 24895
To begin with, Long
is immutable. It means you cannot change the value that you set in the constructor (note the absence of set
methods).
When you do
this.p = this.p + 1;
Java does.
1) Autoconvert this.p
to its long value (primitive)
2) Arithmetic operation
3) Autoconvert the result back to a new, different Long and assign the reference to this.p
t
continues pointing, all the time, to the original Long
object.
In Java, you modify objects through its attributes (not adviceable, you should make them private
) or its methods. A +
(or other operator) will never change an object state (although it may create a new one, in the only case of myString1 + myString2
)
Upvotes: 0
Reputation: 22094
The Long
class is immutable, so you can not pass back the value by modifying it in the called function. In your ClassB
a copy is created and the original value is never changed.
If you want the caller to see the changed value, you must pass it back as return value.
The same is true for the other primitive wrappers and String.
Upvotes: -1
Reputation: 414
Because Java uses pass-by-reference. This means that it passes a copy of the variable, and not a reference to the "original" one.
E.g. in C++, you can do this:
void change_var(int &x)
{
x = 2;
}
int x = 10;
change_var(x);
std::cout << x << std::endl;
This would print 2
, since the reference to the variable x
is being passed, and not a copy.
Upvotes: -2