kzs
kzs

Reputation: 141

Java: Object pointer handling

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

Answers (3)

James P.
James P.

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.

https://softwareengineering.stackexchange.com/questions/141834/how-is-a-java-reference-different-from-a-c-pointer

Upvotes: 0

Pankaj Sharma
Pankaj Sharma

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. enter image description here

Upvotes: 0

Gyanendra Dwivedi
Gyanendra Dwivedi

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

Related Questions