More about Reference Types in Java

Introduction

This post is about the Reference Types in Java and it is a continuation of the post Learning Java the Right Way. In the previous post we discussed about the Reference Types and Values. We will continue that discussion further.

Also, the Java programming language has a lot to offer in terms of Generics, where it becomes almost mandatory to understand about the Types in detail.

Type Declaration Identifiers and Type Names

Now on, whenever we talk about the Types it would mostly be the Reference Types in Java. As Java is an object oriented language, even the primitive types have their object counter parts and Java takes the liberty of auto-boxing and un-boxing.

A class or an interface type consists of a Type Declaration Specifier and can be optionally followed by Type Arguments. If these Type Arguments appear anywhere in a class or interface type, it is a parameterized type.

The above statement is from the JLS, but what exactly does this mean?
Check the below declaration statement.

class MyCoolCar<T extends MyCoolSteering> { }

In the above declaration, MyCoolCar is a type declaration specifier, and the T is a type argument and MyCoolSteering is a bound to the type argument T. Once this declaration is made, we can use T anywhere in the class as below, it is called the parameterized type. This T is passed as a parameter at the time when an instance of this class is created by any of the object creation mechanisms (the new operator).

Objects a classic case of Reference Types in Java

An instance of a class or an array, both qualify to be an object and they are always referenced by some variable. The values of the reference variables are often references which are pointers to these objects. A size of a reference in java is 32 bit or 4 bytes for a 32 bit JVM, it is 64 bit or 8 bytes for a 64 bit JVM. There are possibilities of having compressed references even on a 64 bit JVM. But let us not discuss this further as it is out of the scope of this post.

The value of the reference variable can also contain null which in turn points to no object. Now you might be able to relate why we get a NullPointerException. It is because the value of the reference variable is null, which means it is pointing to no object. Such pointers are called null pointers and as per JLS it is illegal to do any operation on something which is not there (remember there is no object).

Remember that the space occupied by the reference is different then the space occupied by the referenced object. It is not possible to find the space occupied by the object, until the space is actually allocated.

So next time if anyone asks you that what is the space occupied by a variable which points to a huge object, then the answer is either 32 bits or 64 bits.

Role of Auto boxing in object creation

The Java Runtime implicitly creates objects which are new instances of (Boolean, Byte, Short, Character, Integer, Long, Float and Double) in the process of auto boxing all the primitive types (boolean, byte, short, char, int, long, float and double) respectively.

The new operator

The new operator is used to explicitly create objects which are new instances of a defined Type, the Java Framework uses many other ways to create objects but the most commonly used way is new operator. Below are examples of object creation and array creation.
Object obj = new Object();
int[] intArray = new int[10];

Operations which can be performed on object references
  • Dot Operator : It is used to access fields or invoke methods depending on the scope and the accessibility/visibility of the field or method. More on access modifiers in coming posts. For e.g. obj.hashCode() or myCar.currentSteering
  • The Cast Operator : It is used to cast an instance of a give Type T, to a type which lies in the object hierarchy of the Type T. For e.g Number myNumber = (Number)myInt;
  • The instanceof Operator : This operator is used to test if the instance is of a given Type. The result of this operation is a boolean value. For e.g. : myInt instanceof Number returns true if myInt is an instance of any class which lies in the Number hierarchy.
  • The equality operator == or != : This operator is helpful if we want to check two references for equality or inequality.
  • Apart from this we have the concatenation operator + and the conditional operator ? : which can be used for objects.

Some details about the equality operator ==

It is important to understand how the equality operator works, to avoid most of the confusions in the further posts. As we discussed in the beginning of this post, every reference variable stores 32 bit (or 64 bit) value called references and these references either point to a null or a given object.

Now when we compare two reference variables v1 and v2, it compares the 32 bit(or 64 bit) values stored in them. Also, these values are exact memory locations or a JVM understandable or traceable string or number which the JVM can use to trace the object which is pointed by the value of v1 or v2.

Now we all know that the memory locations are always unique and no two objects can be stored at the same memory location at the same time. Hence, this equality operator will always return a false if the pointed objects are not stored in the exact same memory location.

For e.g.:

The moment the new operator is used in the first line, a new memory location is allocated and the object instance is stored in the memory location M1. Now M1 is full, so the second line will instantiate another object and store it at a different memory location M2.
obj1 and obj2 will contain the 32 bit(or 64 bit) value of the respective memory locations. Now we know that addresses of M1 and M2 are not equal.
That is why the evaluation of expression obj1 == obj2 will return false.

Consider another scenario where I also have another object reference declared as Object obj3 = obj1. Then the expression obj1 == obj3 will always return true because the 32 bit(or 64 bit) value assigned to obj3 is from obj1. So both are equal.

Sharing the state of an object

The above discussion hints us that there can be many references to a given object. For e.g. in the above section obj1 and obj3 are pointing to the same object and hence they are equal. The instance of a given Type can store the state of the object in its instance variables. Assume that this instance is being pointed by two references obj1 and obj3, if a change is made to the field using the reference obj1, the change can be observed in the instance pointed by reference obj3 because both are pointing to the exact same instance.

This behavior is only true for Reference Types and not Primitive Types.

Conclusion

We covered most of the details about the Reference Type and now we have a clear understanding to proceed further for more complex but interesting topics in Java. It is really important to read it in a slow and steady way, if we want to be an expert.

I hope this made few things clear and you now know Java better.

If you had difficulty understanding any part of this post, please write your comments. You can also write comments if you liked the post.

Don’t forget to subscribe to TechieMe to get updates on latest posts.