Sai Kumar
Sai Kumar

Reputation: 112

Understanding Reference Behaviour in Java

I was trying something, and I came across this interesting scenario. I just wanted to understand what is the major difference in these two snippets.

Initially, I took two sets, initialized one and assigned the reference to other. When I cleared set A, I noticed that Set B size changed to zero as well

Set<String> A = new HashSet<String>();
A.add("hello");
A.add("HEY");
A.add("hey");
Set<String > B = A;

System.out.println("initial sizes :" + A.size() + "  " + B.size());
A.clear();
System.out.println("final sizes :" + A.size() + "  " + B.size());    

The output of this was something like this :

initial sizes :3  3 
final sizes :0  0    

Now, I tried to depict the same behavior for objects as follows:

Object a1 = new Object();
Object b1 = a1;
System.out.println("initial sizes :" + b1.toString() + "  " + a1.toString());
a1 = null;
System.out.println("initial sizes :" + b1.toString() + "  " + a1);

The output for this was something like :

initial sizes :java.lang.Object@54182d86  java.lang.Object@54182d86
initial sizes :java.lang.Object@54182d86  null

What is the exact difference here, I was expecting to get a NullPointerException when i tried to print b1.toString()

Upvotes: 3

Views: 200

Answers (5)

user3248346
user3248346

Reputation:

For primitives such as int, double, float etc, a copy of the value is made and that is passed by value:-

int x = 10;

public void foo(int k){

}

foo(x)

Here k will get a copy of the value stored in x so k will now have a value of 10. However, x and y are in two different memory locations. Changing the value of x will not change the value of k.

For object references a copy of the reference is made and that is passed by value (a reference is nothing more than the address of some memory). So in essence both references will now point to the same object (that is, the same memory location).

Myobject m = new Myobject();

public void bar (Myobject j){

}

bar(m)

A copy of the value of the reference m will be made and assigned to j. Both m and j will now point to the same object.

Upvotes: 4

ha9u63a7
ha9u63a7

Reputation: 6862

My answer is an additional element to @I.K. answer. Primitives (copy of value) and Non-Primitives (copy of reference values) - that's the key understanding.

Look at this code where I have put the comments (hosted on IDEONE):

import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        String a1 = "blablabla";
        String b1 = a1;

        System.out.println(b1);
        System.out.println(a1);     

        System.out.println(b1.hashCode());
        System.out.println(a1.hashCode());

        a1 = "wow";

        System.out.println(b1.hashCode());
        System.out.println(a1.hashCode());

        System.out.println(b1);
        System.out.println(a1);     

        Set<String> a = new HashSet<String>();

        Set<String> b = a;

        a.add("hey");
        a.add("HellO");

        System.out.println(b.size());
        System.out.println(b.hashCode()); // e.g. 69712814
        System.out.println(a.hashCode()); // same - 69712814 (It's important to know)

        a.clear();

        System.out.println(a.size());  // same hashcode i.e. gets affected by the change.
        System.out.println(b.size());

You can see that they are effectively hashed using the same code.

String class is a bit special in Java as you probably know that they use the String pool for "Intern"ing the values. If you run the code above you can see that as soon as you do a1 = "wow"; it will create a new value "wow" in the pool and therefore, the hashCode() changes.

Upvotes: 0

SomeJavaGuy
SomeJavaGuy

Reputation: 7357

You just noticed that java is completly pass by value, in which even references to other objects are passed as value.

If you null an object you are actually not nulling objects, which methods would be executed on the same object. You are only nulling the value of the reference to the object.

Check this example, you are just nulling the value of the reference on list 1, while you are still able to execute the methods on the original list.

ArrayList<Integer> list1 = new ArrayList<Integer>(0);
list1.add(1);
list1.add(2);
ArrayList<Integer> list2 = list1;
list1.clear();
list1 = null;

System.out.println(list2.size());
System.out.println(list1.size()); // will cause an nullpointerexception

The calls of methods on list1 does also effect list2, but nulling the object list1 wont affect the list 1

Upvotes: 0

Marcin Szymczak
Marcin Szymczak

Reputation: 11453

Check this image. A2/A3 are REFERENCES to bojects. In first case these are references to Set (a1 on image). When one reference modifies object second reference sees the same change

On the other hand if you just set reference = null then you "erase one arrow" from the picture. The reference stops pointing to object, but the other reference still points to it.

enter image description here

Upvotes: 2

blalasaadri
blalasaadri

Reputation: 6218

The difference here, is that a1 and b1 are not the objects themselves but references to those objects. So, if you modify the object referenced by a1 the object referenced by b1 (which is the same object) will change too. If however you tell a1 to point to another instance (or null in this case) it will no longer reference the same object so changes to that won't effect b1.

To go into a little more detail: Java is pass by value. However when you try to pass an object (rather than a primitive value) you're actually passing the value of the reference (also sometimes called the handle). That's why it can sometimes be a bit confusing when trying to determine whether Java is pass by handle or pass by reference.

Upvotes: 3

Related Questions