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.
Related
I have a java pojo class as below
public class ClassA {
private String a;
private String b;
private String c;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
}
And I am using it in another class as below
public class Test {
public static void main(String[] args) {
ClassA ca1 = new ClassA();
ca1.setA("One");
ClassA ca2 = new ClassA();
ca2 = ca1;
System.out.println(ca2);
}
}
The output is: ClassA#53bd815b[a=One,b=<null>,c=<null>]
Is it possible that when I assign ca1 to ca2, ca2 will have only the attribute "a" and not have the other attributes, "b" and "c" as no values are assigned to them?
Your code:
ClassA ca2 = new ClassA();
ca2 = ca1;
… makes no sense. You instantiate a new object of class ClassA. You assign a reference to that object to be stored in a reference variable named ca2. Then you immediately assign another reference to a different object to that same reference variable ca2.
So there was no point to the first of those two lines. Logically, you could replace those two lines with the following, and end up with the same effect.
ClassA ca2 = ca1;
You asked:
is it possible that when I assign ca1 to ca2, ca2 will have only the attribute "a" and not have the other attributes, "b" and "c" as no values are assigned to them.
If you are asking if the second ClassA object can somehow absorb values from the first, the Answer is “No”.
Your two instances of ClassA are separate and distinct from one another. Each holds its own state (member field values). That state is not altered by you assigning a reference to either into a reference variable.
In your Question’s code, you end up with two objects in memory:
One has one member field assigned a value, and the other two yields are null. That object has two reference variables pointing to it.
The other object has all three of its member fields null, with none of the three ever assigned a value. This object has no references left pointing to it. Having no references means this object is effectively “forgotten”, or lost. This object is now a candidate for the garbage collection. After garbage collection, the memory used by this object is freed up to be used for other purposes.
The key concept here is that ca1 and ca2 are not themselves objects. They are reference variables, also known as pointers. They know where to find a particular object. They can each point to different objects, or they can both point to the same object.
See the illustration I made in another Answer of mine on a similar Question.
When you declare ClassA ca2, you are not saying that ca2 is a ClassA, you are saying ca2 will track the location in memory of an object of that class and only that class (and its subclasses).
As for the output of toString being called implicitly by System.out.println, you should override toString yourself to generate whatever output you choose.
I am a bit confused about how this code works can you help. I am trying to understand it in deep. So please feel free to refer any links for depth understanding about the subject matter.The output is A B B A
public class RuntimePolymorphism {
public static void main(String[] args) {
A a = new B();
B b = new B();
System.out.println(a.c + " " + a.getValue()
+ " " + b.getValue() + " " + b.getSuperValue());
}
}
class A {
char c = 'A';
char getValue() {
return c;
}
}
class B extends A {
char c = 'B';
char getValue() {
return c;
}
char getSuperValue() {
return super.c;
}
}
Actually, it's an interesting question ;), by the code, from the fist sight, I would say, it should output A A B A, yet it producing A B B A.
Then, I found a possible typo (or it was intentional, don't know):
A a = new B();
B b = new B();
we have two B's here, but we are also doing a type casting at the moment of instantiation of a variable. Even if we make c field as public it still produces the same result.
But, on the other hand, if we'll update to code like this:
A a = new A();
B b = new B();
everything will be as expected: A A B A.
Interesting finding: if we remove overloaded getValue() from the B class, the output will be A A A A...
Final conclusion: we can inherit a non-private field (that's we can access it from derived class), but we can't "overload" it the way we do with methods.
Thus, in Java, polymorphism is only working with methods and not with the fields.
The instance variable C from A is simply hidden in B
– A.C is ‘A’ because it's set in the class A
– A.getValue() returns ‘B’ because the object is of type B
So I think we should first understand the difference between Hiding and Polymorphism.
When you declare a subclass with a variable name the same as the superclass variable, then the subclass variable just hides the superclass variable.
For Runtime Polymorphism, a subclass method would need to override a superclass method. When a method in a subclass has the signature ( name and parameters ) and same return type as a method in its superclass, then the method in the subclass overrides the method in the superclass.
Another important point is that Polymorphismm ( Runtime in this case ) acts on methods that are evaluated at run time. But the initialization of values to the variables happens at compile time.
So, when A a = new B(); is executed, a's instance variable c has the value 'A'. So even if the reference a is pointing to a B object, the instance variables it refers to would be that of A.
Hence the output when we run a.c would be A.
But since the method getValue() is overriden in the subclass, a would call the overriden method ( because it is pointing to the subclass B object ).
Hence the output when we run a.getValue() would be B
So, when B b = new B(); is executed, b's instance variable c has the value 'B'. And this hides the variable c of the superclass. And if we want to refer to the immediate superclass's instance variables then we access it via super.<variable_name> So even if the reference a is pointing to a B object, the instance variables it refers to would be that of A.
The reference b is pointing to an object of type B and hence it would call B's getValue() method.
Hence the output when we run b.getValue() would be B.
As discussed above, we access the immediate superclass's instance variables via super.<variable_name>
Hence the output when we run b.getSuperValue() would be A
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).
I need to get some clarification on Java references (pointers).
I have read this (Java is Pass-by-Value, Dammit! by Scott Stanchfield) excellent write up on Java's way of passing variables around. As far as I understand everything is passed around as memory pointers.
public class foo{
int a;
int b;
public foo(a, b){
this.a = a;
this.b = b;
}
}
so in some code like this:
foo aFoo = new foo(1,2); //new foo created at adress 0x40 for instance
someFunc(aFoo);
the argument to someFuncis actually the number 0x40 (albeit this might be a simplification, but to get a sense for the pattern).
Now, suppose i created another class
public class bar{
foo aFoo;
public bar(){
this.aFoo = new foo(1,2);
}
}
and instantiated the following variables
bar aBar = new bar();
foo bFoo = new foo(3,4);
now suppose i want to copy the values of aBar.aFoo into bFoo like
bFoo = aBar.aFoo;
If i now do
bFoo.a = 1234;
did i also just change aBar.aFoo.a into 1234 or does that variable still hold the value 1?
By my own logic, bFoo.a is just a pointer, so assigning a new variable should alter both places, but this seems incorrect. So I guess i have not fully understood Java's "reference is really a pointer" concept. Or rather, i might understand the pointer part of it, but not the dereferencing of the pointers, since this is done implicitly compared to in C where you always know.
bFoo = aBar.aFoo;
-> you have assigned the aBar.aFoo reference to bFoo local variable. This is called aliasing because now you have two ways to refer to the same object: bFoo and aBar.aFoo.
bFoo.a = 1234;
-> you have assigned 1234 to the a field of the object referred to by bFoo. This object is referred to by aBar.aFoo as well.
Result: you have changed the value of aBar.aFoo.a.
If arrays are object as stated in Is an array an object in java then why the output of the code snipped below is [1,1,1]?
I thought after the execution of statement "a=b;" a and b are still pointing to the same content! Isn't it supposed to be shadow copy between objects?
import java.util.Arrays;
public class Local {
int [] a = null;
public Local(){
int [] b = {1,1,1};
int [] c = {5,5};
a=b;
b=c;// 'a' should change too as a and b are both objects! right?
}
public static void main(String[] args) {
Local local = new Local();
System.out.println(Arrays.toString(local.a));
}
}
Let me try to explain it line per line:
int [] b = {1,1,1};
On this line, three things happened.
Created a variable named b.
Created an array of int {1,1,1}
Assigned b to the array of intcreated on step 2.
int [] c = {5,5};
Same thing happened here
Created a variable named c.
Created an array of int {5,5}
Assigned c to the array of int created on step 2.
a=b;
Now we also assigned a to whatever the value of b is, which in this case is the array of int {1,1,1}
Now we have something like
b=c; // 'a' should change too as a and b are both objects! right?
What happened here is that we assigned b to whatever c's value is (int array {5,5}), now b is not pointing to {1,1,1} anymore and since Java is pass by value, a's value remained. It's not like a is pointing to the reference of b that whatever b is pointing to, a will point to it too.
Hope this helps.
// 'a' should change too as a and b are both objects! right?
No both a and b are just reference variables pointing to the same array object {1,1,1}.
With the below line you are making b to refer to altogether different array object where as a would still be pointing to the same array object {1,1,1} as the reference of only b but not a is changed by executing the below line
b = new int[] {2, 2};
Also by making a = b you are making them point to one single array object {1,1,1} and there is no deep/shallow copy happening here.
the variable a would not automatically update itself. mainly because
b = c //is like b = new int[]{5,5};
it is the same concept in your question earlier with
b = new int[]{2,2,2};
a is pointing to b's int array which is [1,1,1]
and you are telling b to point to c which is [5,5]
a => b's array
b => c's array
so a will retain its object and b will have a new one.
At first, b is pointed to the array object {1,1,1}
and you assign b to a, so a is pointed to {1,1,1}
so the out is {1,1,1}