Difference between Primitive and Reference variable in Java

There are two types of variables in Java, primitive and reference type. All the basic types e.g. int, boolean, char, short, float, long and double are known as primitive types. JVM treats them differently than reference types, which is used to point objects e.g. String, Thread, File and others. Reference variables are not pointers but a handle to the object which is created in heap memory. The main difference between primitive and reference type is that primitive type always has a value, it can never be null but reference type can be null, which denotes the absence of value. So if you create a primitive variable of type int and forget to initialize it then it's value would be 0, the default value of integral type in Java, but a reference variable by default has a null value, which means no reference is assigned to it.


If you try to access any field or invoke a method on a null reference, you will be greeted with NullPointerException in Java. It's very important for every Java developer to understand difference between primitive and reference variable in different cases e.g. while assigning values, comparing values, passing them as method arguments and returning them from methods, to avoid nasty errors e.g. null pointer exception.

In short, the main difference between two types is that primitive types store actual values but reference type stores handle to object in the heap. Head First Java 2nd Edition also explains this key concept clearly, So you can also take a look there to understand it bit more.

Primitive vs Reference variable in Java



Difference between Primitive vs Reference variable

Now, we know the purpose of both types of variable, its time to take a deep dive into some more differences between primitive and reference variables in Java.



Default value and Null
First difference between primitive and reference type is that former can never be null if no value is assigned they take their default value e.g. boolean variable will be initialized with false, byte, short, char,int and long will be initialized with zero, and float and double variables will be initialized with 0.0 value in Java.

Here is a classification of all primitive and reference type in Java :

Primitive vs Reference Type in Java


What do they store?
The second difference is that primitive types stores values but reference type stores handle to object in heap space. Remember, reference variables are not pointers like you might have seen in C and C++, they are just a handle to object so that you can access them and make some change on object's state.



Assigning value using Assignment Variable (=)
When you assign a value to primitive data types, the primitive value is copied, but when you assign an object to reference type, the handle is copied. which means for reference type object is not copied only the handle is copied, i.e. the object is shared between two reference variable, known as aliases. An implication of this is modification done by one variable will affect to other.

int i = 20;
int j = i;
j++; // will not affect i, j will be 21 but i will still be 20

System.out.printf("value of i and j after modification i: %d, j: %d %n", i, j);

List<String> list = new ArrayList(2);
List<String> copy = list;  

copy.add("EUR"); // adding a new element into list, it would be visible to both list and copy
System.out.printf("value of list and copy after modification list: %s, copy: %s %n", list, copy);

Output :
value of i and j after modification i: 20, j: 21 
value of list and copy after modification list: [EUR], copy: [EUR]

You can see that modification on one primitive variable doesn't affect the copy but it does in the case of the reference variable. This sometimes creates confusion between programmer that Java is not passed by value for the reference type, which is not correct, Java is always passed by value, be it references or primitive variables.

Here is a diagram which clearly shows the difference about how assignment operator works differently on primitive and reference variable in Java :

Difference between Primitive and Reference variable in Java


Comparison using == operator
When you compare primitive variables using equality (==) operator, their primitive values are compared but when you compare reference variable, their address is compared, which means two objects which are logically equal e.g. two String object with same content may be seen as not equal, as seen below :

int i = 20;
int j = 20;

if (i == j) {
    System.out.println("i and j are equal");
}

String JPY = new String("JPY");
String YEN = new String("JPY");

if (JPY == YEN) {
    System.out.println("JPY and YEN are same");
}

if (JPY.equals(YEN)) {
    System.out.println("JPY and YEN are equal by equals()");
}

Output :
i and j are equal
JPY and YEN are equal by equals()

You can see that primitive variable are rightly compared using == operator, but when we compared two String object with same contents i.e. "JPY", they are not equal using == operator, that's why the second line is not printed, but when I compared them using equals() method, they are considered equal. This means you should always use equals() method to compare reference types.


Passing primitive and reference variable as method argument
When you pass primitive values to a method the values are passed to the method, but when you pass reference variable, only the handle is copied. which means for primitives, changing the formal parameter's value doesn't affect the actual parameter's value, while in case of reference types, changing the formal parameter's handle doesn't affect the actual parameter's address but changing the formal parameter's internal values does affect actual parameter's object, because they refer to the same object in memory. See Core Java Volume 1 10th Edition by Cay S. Horstmann to learn more.

What is reference variable in Java


For those, who are not aware of formal and actual parameters, formal parameters are those, which is listed(along with its type) in method declaration e.g. on getName(Employee e) , e is a formal parameter. While actual parameters are those which are passed to method during invocation e.g. getName(new Employee("John")).

Here is the proof of I just said :

/**
 * Program to demonstrate difference between primitive and reference type
 * variable in Java.
 * 
 * @author WINDOWS 8
 *
 */
public class PrimitiveVsReference{

    private static class Counter {
        private int count;

        public void advance(int number) {
            count += number;
        }

        public int getCount() {
            return count;
        }
    }

    public static void main(String args[]) {        
        int i = 30;
        System.out.println("value of i before passing to method : " + i);
        print(30);
        System.out.println("value of i after passing to method : " + i);
        
        Counter myCounter = new Counter();
        System.out.println("counter before passing to method : " + myCounter.getCount());
        print(myCounter);
        System.out.println("counter after passing to method : " + myCounter.getCount());
    }

    /*
     * print given reference variable's value
     */
    public static void print(Counter ctr) {
        ctr.advance(2);
    }
    
    /**
     * print given primitive value
     */
    public static void print(int value) {
        value++;
    }

}

Output :
value of i before passing to method : 30
value of i after passing to method : 30
counter before passing to method : 0
counter after passing to method : 2

You can see that changing formal parameter's value doesn't affect actual parameter's value in case of primitive variable but it does in the case of the reference variable, but only if you change the state of an object.


Return value of a method
When you return primitive types from a method then the primitive value is returned but when you return a reference type, again only handle to the is returned. This means a locally created object can survive even after method finishes its execution, if it was returned from a method or if it was stored in any member variable, why? because object is always created in heap memory. while all primitive local variables are destroyed after method finishes execution.


Stack vs Heap
Primitive variables are created in the stack while reference variable is created in heap space, which is managed by Garbage Collector. See the difference between stack and heap memory in Java, for more details.


Memory consumption or Size
Primitive variables take less memory than reference variable because they don't need to maintain object metadata e.g. object header. An int primitive variable will take less memory than Integer object for storing same value e.g. 5.


That's all about the difference between primitive and reference variable in Java. Always remember that primitive variables are by default initialized to their default value, which is not null and they will not throw NullPointerException, but if you access an uninitialized reference variable it will throw NullPointerException.

Primitive variables are also copied when you assign them to another primitive variable and change on one variable will not affect other, but in the case of the reference variable, the handle is shared between multiple reference variable and any change into object's state will be visible to all reference variable.

Another key difference between primitive and reference variable to note is that former take less memory than later due to object metadata overhead e.g. memory require holding object header. An int primitive variable will always take less memory than Integer object for storing same value.

Other related articles and interview questions you may find useful :
  • What is the difference between C++ and Java constructor? (answer)
  • Difference between SOAP and REST Web Service in Java? (answer)
  • Difference between HashMap, TreeMap and LinkedHashMap in Java? (answer)
  • What is the difference between direct, non-direct and mapped buffer in Java? (answer)
  • What is the difference between Factory pattern and dependency Injection? (answer)
  • How do you calculate the difference between two dates in Java? (answer)
  • Difference between Composition and Inheritance in OOP? (answer)
  • 10 differences between JavaScript and Java? (answer)
  • Difference between Maven, ANT and Jenkins in Java world (answer)
  • Difference between ArrayList and LinkedList in Java? (answer)
  • What is difference between transient and volatile variable in Java? (answer)
  • Some key difference between Vector and ArrayList in Java? (answer)
  • Difference between get() and load() method in Hibernate? (answer)

No comments :

Post a Comment