Reputation: 141
Let's say I have this Java code (midterm review!):
public class A {
public int key;
}
public class B extends A {
}
public class Problem1 {
public static void f(A x) {
A y = x;
y.key = x.key + 1;
}
public static void f(B x) {
B y = new B();
y.key = x.key + 2;
x = y;
}
public static void main(String[] args) {
A p = new A();
p.key = 3;
B q = new B();
q.key = 10;
f(p);
f(q);
p = q;
f(p);
System.out.println(p.key);
}
}
I'm not sure I properly understand p = q. Here's my understanding thus far: because B extends A, this operation is allowed but it doesn't make p and q point to the same object. Rather, it updates the key value for p but it remains of class A. Which is why f(p) at the end returns 11. This doesn't follow with what I thought I knew about Java previously so an explanation would be appreciated.
For example if I have int a = 4 and int b = 3, then I do:
a = b;
b++;
return a;
a will return 3, even though it should be pointing to the same thing that b is pointing to?
Please advise.
Upvotes: 0
Views: 2681
Reputation: 19617
For example if I have int a = 4 and int b = 3, then I do:
a = b; b++; return a;
a will return 3, even though it should be pointing to the same thing that b is pointing to?
Primitives are handled as you'd expect them to. In other words, a will give the value 3 because it has taken up the numeric or bit value of b. However, you should look into autoboxing and immutability.
I'm not sure I properly understand p = q. Here's my understanding thus far: because B extends A, this operation is allowed but it doesn't make p and q point to the same object. Rather, it updates the key value for p but it remains of class A.
With respect to objects, the operation p = q
does actually assign p such that it "refers" (see link at bottom) to the same object as q. That's why approaches like defensive copying are necessary.
This also explains why modifications are taking place despite Java passing by value through the overloaded f
methods. Parameter x
remains as is, disappearing as soon as a process leaves the method scope, but the state of the referred object can be modified.
Here's a question that goes into the differences between C pointers and Java references.
Upvotes: 0
Reputation: 1853
all variables are bit holders. ok
so if it is primitive type it will be holding bits which represent a bit lavel representation of primitive .
a = b; b++; return a;
here bits representation of "3" is assigned to "a" so it is 3 now. but b still holding bits representing "3" so cange in b will stick to just "b"
now if a is a class variable and b also, in java variables always holds bit. when it is class
varible it hold the bits which represent the path to reach the class object which is living on heap. so when you do this a = b;
a will also hold the path to reach the object which is living on heap . so "a" and "b" both holding path to same object.
if you change in property of "a"( change property of object which is reached by path which is holded by var "a") . will reflect in b. because these are pointing to same var.
Upvotes: 0
Reputation: 5557
Think about it. The Java primitive holds the actual value in the memory byte area:
So if a = 4
and b = 3
, then a 8-byte machine memory area may hold it like (in binary)
a = 0 0 0 0 0 0 1 1
b = 0 0 0 0 0 0 1 0
Now, when you say a=b;
means
a = 0 0 0 0 0 0 1 0
b = 0 0 0 0 0 0 1 0
Then b++ (i.e. b = b+1)
a = 0 0 0 0 0 0 1 0
b = 0 0 0 0 0 0 1 1
Then
return a;
Then a = 0 0 0 0 0 0 1 0 (i.e. 3)
Hope you understand it for a primitive value. Though for an object in java this is a different case altogether.
Now think, a and b are NOT primitive, rather object having a int field. A Sample class may look like
class Test {
private int value;
public Test(int value){
this.value = value;
}
public int getValue(){
return value;
}
public int increment(){
value++;
}
}
Then a = new Test(4); and b = new Test(3);
is represented in memory like:
Heap:
a = x63489DF8 ---> [Test(4) Object, value = 4, Heap Memory address = x63489DF8]
b = xDFA78945 ---> [Test(3) Object, value = 3, Heap Memory address = xDFA78945]
(a
and b
holds a heap memory address which points to the objects)
Now, when you say a=b;
means
a = xDFA78945 ---> [Test(3) Object value = 3, Heap Memory address = xDFA78945]
b = xDFA78945 ---> [Test(3) Object value = 3, Heap Memory address = xDFA78945]
(the object in memory address x63489DF8
is garbage collectible and a, b
are referring to same object)
Now, say b.increment();
then the object in memory area xDFA78945
is manipulated and new object becomes [Test(3) Object value = 4, Heap Memory address = xDFA78945]
.
a = xDFA78945 ---> [Test(3) Object value = 4, Heap Memory address = xDFA78945]
b = xDFA78945 ---> [Test(3) Object value = 4, Heap Memory address = xDFA78945]
(Note that the change reflect both the reference, because both are actually pointing to the same object)
Now return a.getValue()
returns 4.
(i.e. change done through reference b
reflects back in reference a
as well)
Upvotes: 1