Deep Dive into Inner and Nested Classes in Java

Deep Dive into Inner and Nested Classes in Java

Inner class is one of the topics in Java that I used to find difficult, so I thought to go deep into its concepts and share this with you guys.
You may feel this article longer but it will be worth a read.
So let's start...

What is Inner Class?

When a class is declared inside another class or interface, it is called an inner or nested class.

Why inner classes?

Suppose there is a case, without existing an object of one type, there is no chance of existing another type object, then we can go for inner classes.

Eg1:- Suppose we have a Car object and as we know there are many components in a Car and one of its important parts is Engine, also without having a Car object there is no sense of having an Engine object.
Here, we can declare an Engine class inside Car

class Car{
    class Engine{

    }
}

Eg2:- Similarly, in the Map interface, we have key-value pairs.
Each pair is called an Entry.
So, without having a map object there is no chance of having an entry object.
Therefore if we see the Map interface, the Entry interface is defined inside it.

Relation between Outer class and Inner Class

If you have an idea about Inheritance, two classes have a parent-child relationship.
For eg: A dog is-a an Animal, Cat is-a an Animal.
So in inheritance, we have an IS-A relationship between 2 classes.

But in the case of inner classes, the relationship is HAS-A.
Car has-a Engine, Map has-a Entry.

Types of Inner class

Based on the position and behavior of the classes, inner classed are divided into 4 types:

  1. Normal or Regular Inner Class
  2. Method Local Inner Class (class inside a method)
  3. Annonymous Class ( class with no name)
  4. Static Nested Class (class with static keyword)

Normal or Regular class

When we declare any named class directly inside a class without a static modifier such class is called a normal or regular inner class.

class Outer{

    class Inner{ //normal inner class

    }
}

When we compile this, how many class files will be generated?
2 (.class) file will be generated

Outer.class
Outer$Inner.class

Why an inner class cannot have static declarations?

As we discussed, without having an Outer class object we cannot access the Inner class.
But to access static members there is no requirement of object/instance. Therefore, we can't have static declaration inside the Inner class.

carbon (25).png

Different ways of interacting with Inner Class

Case 1 - Accessing inner class code from a static area of the outer class

To access the inner class method m1(), we require an inner class object.
To get an inner class object, we require an Outer class object.
So, first, create an Outer class object.
Now, to create an inner class object we will use the outer object(o) then new Inner().

carbon (26).png

Case 2 - Accessing inner class code from the instance area of the Outer class.

carbon (27).png

To access the inner class method m1() from the outer class method m2(), we can just create an Inner class object and access it.
But there might be a question, how do we access the Inner class without the Outer class object?
We have reached the instance method of outer class m2() with the outer object, which means we have an outer class object now we can create inner class object easily.

Case 3 - Accessing inner class code from a static area of another class

This is the same as case 1

carbon (28).png

Case 4 - Accessing static and non-static members of an outer class from inner class

carbon (29).png

Note - we discussed earlier that we can't declare static members inside the inner class but we can definitely access static members of the outer class directly from the inner class.

Case 5 - Use of 'this' in Inner class

If there is a naming conflict in the outer and inner class, this keyword plays an important role.
Let's see an example.

carbon (30).png

Here, we have an instance variable 'x' in Outer class, Inner class, and method of Inner class.

Within the inner class, the 'this' keyword refers current inner class object.
So, to print the value of the instance variable of the inner class we used this.x.
Now to print the value of 'x' of the Outer class, we used Outer.this.x

Method local inner classes

Sometimes we can declare a class inside a method, such inner classes are called method local inner classes.

What is the need?

The main purpose of the method local inner class is to provide method-specific repeated functionality.
For example, we have a method m1() and in that, we need to perform some operation multiple times, so the best method is to create a method m2().
But the condition is we can't declare m2() as another class-level method, as m2() is very specific to m1().
So what we can do is create m2() inside m1().

carbon (31).png

But nested methods are not allowed in Java.
So, here comes Method Local Inner Class i.e a class inside a method.

carbon (32).png We can just create an Inner class object and access m2().
Method Local Inner Class is best suited to meet nested method requirements.

When we create any variable in a method that is local to that method only.
Similarly, Method Local Inner Class is local to the method where it is declared.

Method Local Inner Class inside a static and non-static method.

When a class is declared inside a non-static/instance method then we can access both instance and static members of the outer class.

carbon (33).png

But when a class is declared inside the static method then only static members of the Outer class can be accessed because when we create a static method, its area will be static, and in static area/context, we can't access instance members.

carbon (34).png

Anonymous Inner Class

Inner Classes which do not have a name is called Anonymous Inner class.
When we want a class just for instant use or one-time usage and we don't care about its name for the future, then we can create an Annonymous Inner class.

How to create an Anonymous Inner class?

carbon (37).png

In statement 1, we have created a Student object with a new keyword.
In statement 2, instead of a semicolon (;) we have used
{

};
This means we are creating a class which is a child Student class, as it does not have a specific name we call it Anonymous Inner class.
Here,

 Student s = new Student()
`  {
        //some code
   };

means we are creating the object of the child class of Student and using the reference variable of Student class(parent).

Types of Anonymous Inner classes

Based on declaration and behavior there are 3 types of Anonymous Inner class

  1. Anonymous Inner class which extends a class.
  2. Anonymous Inner class which extends an interface.

Anonymous Inner class which extends a class

Consider the below example,

carbon (39).png

We have a Student class and it has a method plays().
In the Test class, we have created a Student object s1.
Also, for Student s2, we want to override the plays() method because Student s2 wants to play FootBall.

So, we can create a top-level child class of Student and override the plays() method but we want this class only once.
So instead of creating a named class, we have created an anonymous class that extends the Student class and we are overriding the plays() method.

When we compile the above file, 3 .class files will be generated

  1. Student.class
  2. Test.class
  3. Test$1.class - this is the underlying name of the Anonymous Inner class which we created for s2.
    As this class is created in Test class and it is the first inner class so the name - Test$1

Anonymous Inner class which implements an interface

In a similar way, we can define anonymous inner class by implementing an interface

carbon (38).png

Difference between Normal Java class and Anonymous Inner class

image.png

Static Nested classes

Sometimes we declare an inner class with static modifiers such class is called a static nested class.
Up to this, we have covered

  1. Regular Inner Class
  2. Method Local Inner Class
  3. Anonymous Inner Class

Why it is called Nested instead of Inner?

When we create a regular inner class, it is strongly associated with the outer class. Without the outer class object, we cannot reach the inner class.

carbon (40).png

Now let's make the inner class static.

carbon (42).png

As the class is static, without having an outer class object we can reach a static inner class.
There is no strong association.
Therefore instead of calling it static inner class, we call it static nested class because the class is just nested and it is not strongly associated with the outer class.

carbon (41).png

Access static class from Outer class main method

carbon (43).png

We have created a static nested class and main() method in the outer class.
As we discussed, we don't require Outer class objects to access static nested classes, we can directly create Nested object.

Access static class outside of Outer class.

carbon (44).png

We have created main() inside the Test class.
Now we want to create a static nested class object, but as this class is nested we need to specify where the static nested class is located.
Therefore, we are using Outer.Nested.

Accessing outer class members from the static nested class

We have an instance variable 'x' and static variable 'y'.
When we try to access instance variable x from the static nested class, we get a compile-time error.

non-static variable x cannot be referenced from a static context

carbon (46).png

Difference between Normal Inner Class and Static Nested Class

image.png

Conclusion

So far we have covered,4 different types of inner/nested classes and their usage.
I hope I was able to explain to you all the concepts.

Reference - Have a look at the playlist on YouTube which you can refer to if you want to learn through amazing videos.

If you find this helpful, do like it.
If you are interested in this type of blog, Follow Me✔
Feedback and Suggestions are welcome.
Good Bye👋
Keep Learning📚