Nead clarification for following code:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
This will print B
so that proves sample
and referToSample
objects refer to the same memory reference.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
This will print AB
that also proves the same.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
Obviously this will throw NullPointerException
because I am trying to call append
on a null reference.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
So Here is my question, why is the last code sample not throwing NullPointerException
because what I see and understand from first two examples is if two objects referring to same object then if we change any value then it will also reflect to other because both are pointing to same memory reference. So why is that rule not applying here? If I assign null
to referToSample then sample should also be null and it should throw a NullPointerException but it is not throwing one, why?
In a nutshell: You assign null to a reference variable, not to an object.
In one example you change the state of an object that is referred to by two reference variables. When this occurs, both reference variables will reflect the change.
In another example, you change the reference assigned to one variable, but this has no effect on the object itself, and so the second variable, which still refers to the original object, will not notice any change in object state.
So as to your specific "rules":
Again, you refer to changing the state of the one object that both variables refer to.
Again, you change the reference of one variable which has absolutely no effect on the reference of the other variable.
These are two completely different actions and will result in two completely different results.
Just easy, Java don't have pass by reference, It just pass object reference.
Initially it was as you said
referToSample
was referring tosample
as shown below:1. Scenario1:
2. Scenario1 (cont.):
Here as
referToSample
was referring tosample
, so it appended "B" while you writereferToSample.append("B")
Same thing happend in Scenario2 :
But, in 3. Scenario3 : as hexafraction said,
when you assign
null
toreferToSample
when it was referringsample
it did not change value instead it just breaks the reference fromsample
, and now it points nowhere. as shown below:Now, as
referToSample
points nowhere, so while youreferToSample.append("A");
it would not be have any values or reference where it can append A. So, it would throwNullPointerException
.BUT
sample
is still the same as you had initialized it withStringBuilder sample = new StringBuilder();
so it has been initalized, so now it can append A, and will not throwNullPointerException
Here 'sample' and 'referToSample' are referencing the same object.That is the concept of different pointer accessing same memory location. So assigning one reference variable to null does not destroy the object.
means 'referToSample' only pointing to null , object remains same and other reference variable are working fine. So for 'sample' which does not pointing to null and have a valid object
works fine. But if we try to append null to 'referToSample', it will show NullPointException. That is,
That is why you got NullPointerException in your third code snippet.
null
assignments do not change value by globally destroying that object. That kind of behavior would lead to hard-to-track bugs and counterintuitive behavior. They only break that specific reference.For simplicity, let's say that
sample
points to address 12345. This is probably not the address, and is only used to make things simple here.The address is typically represented with the weird hexadecimal given in1Object#hashCode()
, but this is implementation-dependent.From the lines marked
See diagram
the diagrams of the objects at that time are as follows:Diagram 1:
Diagram 2:
Diagram 2 shows that annulling
referToSample
does not break the reference ofsample
to the StringBuilder at00012345
.1GC considerations make this implausible.
See this simple diagram:
When you call a method on
referToSample
, then[your object]
is updated, so it affectssample
too. But when you sayreferToSample = null
, then you're simply changing whatreferToSample
refers to.