Inner Classes or Non-static Nested Classes in Java

Inner Classes or Non-static Nested Classes in Java

Java inner class or non-static nested class is the most prevalent type of nested class among those Java provides. A Java inner class has access to all of the methods and variables (even they are private) of the enclosing class as if these methods and variables have been declared within the inner class. But the opposite is not true; enclosing class cannot access directly the members of inner class.

Let's see how is a Java inner class defined and compiled?

/* OuterClass.java */
 
public class OuterClass
{
    class InnerClass
    {
        //non-static inner class
    }
}
 
 
[root@host ~]#javac OuterClass.java
[root@host ~]#ls
...
OuterClass$InnerClass.class  OuterClass.class
...

After compiling OuterClass.java you see there are two class files are generated. It is because Java generates separate class file for every class even if it is an inner class. Here InnerClass is an inner class yet it is a separate class so a separate class file is generated. But, remember that you cannot access OuterClass$InnerClass.class in a usual way as you access top level classes. The only way you can access the Java inner class is through a live instance of the enclosing outer class.

How to Instantiate Java Inner Class?

As it has been mentioned, a Java inner class can be accessed only through a live instance of outer class. So, to create an instance of Java inner class (InnerClass) you must have an instance of enclosing outer class (OuterClass).

Mostly, Java inner classes are defined to assist outer classes in some way, so it is the outer class usually creates instance(s) of inner class. Let's modify the OuterClass to create an instance of InnerClass.

/* OuterClass.java */
 
public class OuterClass
{
  private int outerMem = 10;
 
  public void createInnerClassInst()
  {
    InnerClass ic = new InnerClass();
    ic.getOuterMem();
  }
 
  class InnerClass
  {
    public void getOuterMem()
    {
      System.out.println("OuterMem accessed from InnerClass: " + outerMem);
    }
  } //InnerClass closed
} //OuterClass closed

See the above code where OuterClass code treats InnerClass as if InnerClass is any other accessible class. Within from the method createInnerClassInst(), class OuterClass creates an object using the class name new InnerClass(), and then invokes the method getOuterMem() on the reference variable as ic.getOuterMem().

The below piece of code demonstrates object creation of OuterClass and then access its own member outerMem through an object of InnerClass.

/* InnerClassDemo.java */
 
public class InnerClassDemo
{
    public static void main(String[] args)
    {		
        OuterClass oc = new OuterClass();
        oc.createInnerClassInst();
    }
}
 
OUTPUT
------
OuterMem accessed from InnerClass: 10

Above piece of code works because the OuterClass instance oc calls createInnerClassInst() method that instantiates an object of InnerClass. So there should be an instance of outer class that further creates an instance of Java inner class (InnerClass).

How to Instantiate Java Inner Class Object from Outside the Outer Class?

You may now be thinking that is there any way to create an object of Java inner class InnerClass from somewhere outside the outer class OuterClass? Is it possible? Of course it is, but in that case the visibility of the Java inner class should either be default or public. In our example code the visibility of InnerClass is default, thus it is visible within the same package.

So, if we want to create an instance of Java inner class InnerClass somewhere outside the outer class OuterClass instance code then we must have an instance of OuterClass. As you already know that without an object of the outer class you cannot create an object of the Java inner class from any other code in any other class. A Java inner class object is always bounded to an outer class object. The compiler takes care of it and you see the end results only (the ability to access members of outer class). Have a look at following piece of code and you will understand.

public class InnerClassDemo
{
    public static void main(String[] args)
    {		
        OuterClass oc = new OuterClass();
        oc.createInnerClassInst();
 
        // Creating InnerClass's instance by 
        // an instance of OuterClass 'oc'
        OuterClass.InnerClass icc = oc.new InnerClass();
        icc.getOuterMem();
 
        //One liner way to create an inner class object
        OuterClass.InnerClass iccc = new OuterClass().new InnerClass();
        iccc.getOuterMem();
   }
}
 
OUTPUT
------
OuterMem accessed from InnerClass: 10
OuterMem accessed from InnerClass: 10
OuterMem accessed from InnerClass: 10

Read the above piece of code carefully and see the difference between inner class object creation code that is within outer class, and inner class object creation code that is outside the outer class:

  • From inside the outer class instance code we use the inner class name in the usual way:
    InnerClass ic = new InnerClass();
  • From outside the outer class instance code, the inner class name must now include the outer class's name:
    new OuterClass().new InnerClass(); or oc.new InnerClass();
    oc is already created instance of OuterClass.

Accessing Outer Class Instance in Java Inner Class

In order to understand accessing outer class instance within from Java inner class we have to first look at the functionality of this operator. As we know an object refers to itself by using this reference. But, this reference has some limitations. First, this can be used within from non-static instance code only, not within from static methods because static methods can be executed even without creating an object. Second, this refers to the current object. And third, this reference is the way an object can pass a reference to itself.

Within a Java inner class this reference refers to the instance of the inner class. But, if you sometimes need an explicit reference to the outer class or enclosing class instance that the inner class is tied to then use OuterClass.this. Following is an example:

/* InnerOuterThisDemo.java */
 
public class InnerOuterThisDemo
{
    public static void main(String[] args)
    {
        Outer.Inner i = new Outer().new Inner();
        i.AccessOuterThis();
    }
}
 
class Outer 
{
    int onum = 10;
 
    class Inner 
    {		
        public void AccessOuterThis ()
        {
            System.out.println("Outer member onum: " + onum);
            System.out.println("Inner class reference is: " + this);
            System.out.println("Outer class reference is: " + Outer.this);
        }
    }
}
 
OUTPUT
------
Outer member onum: 10
Inner class reference is: Outer$Inner@360be0
Outer class reference is: Outer@45a877

The output from above code gives you the class name followed by @ symbol, followed by the unsigned hexadecimal representation of the object's hash code.

Last Word

In this tutorial we talked of Java inner class. A Java inner class is a member of the outer class just like other variables and methods, so the same modifiers applied to other variables can be applied to Java inner class too. For example a Java inner class can be declared final, abstract, public, private, protected, and strictfp but static. Because static turns it into a Java static nested class not a Java inner class. Hope you have enjoyed reading this tutorial. Please do write us if you have any suggestion/comment or come across any error on this page. Thanks for reading!

References



Share this page on WhatsApp

Get Free Tutorials by Email

About the Author

is the founder and main contributor for cs-fundamentals.com. He is a software professional (post graduated from BITS-Pilani) and loves writing technical articles on programming and data structures.