A nested class as the name suggests is a class that is defined inside another class. It is merely a convenient way of grouping two or more classes together into a single unit or module. A class that contains a nested class is known as the enclosing or outer class of the nested class.
Nested classes are used for a variety of purposes such as
• GUI event handling.
• Hiding a class from other classes in the same package.
• As helper classes to perform some specific function ( such as implementing a particular action) or to provide a specific view onto some data (by providing an iterator or enumerator etc.)
• An object of the inner class can access the implementation of the object that created it, including data that would otherwise be private.
• Allows implementing the same interface more than once in a class.
• Make the code more readable and maintainable as it is placed closer to where it is used.
Nested classes are divided into two categories: Static nested classes and non-static nested classes. Non-static nested classes are also called inner classes. The Inner classes can be further classified into three types: Regular inner classes, Locale inner classes, and Anonymous inner classes.
We’ll be covering the following topics in this tutorial:
Regular Inner Class
A regular inner class is a nested class that only exists within an instance of enclosing class.
In other words, you cannot instantiate an object of an inner class without first having an object of the outer class. An inner class can use all the methods and fields of the outer class even the private ones directly. The methods and fields of an outer class are used as if they were part of the inner class. An inner class is declared in the same way as any other class but should be inside some other class. The basic structure of creating an inner class is as follows,
public class OuterClass {
public class InnerClass {
//body of inner class
}
//More members of outside class
}
From the above structure, it is clear that the class InnerClass acts as a member of the enclosing class OuterClass in much the same way as its other members. So it can be marked with an access specifier, to specify whether the class should be public, protected or private. If none of the access specifiers is specified then default package access specifier is used. These access specifiers determine whether other classes can access the inner class or not.
More often it is the outer class that creates an instance of the inner class since it is usually the outer class that wants to use the inner instance as a helper object for its personal private use. To create an instance of the inner class, you must have the instance of the enclosing class so that you can associate them. To create an object of type InnerClass you have to write the following statement.
OuterClass outer = new OuterClass();
OuterClass.lnnerClass inner = outer.new InnerClass();
The following program demonstrates the concept of inner class
//use of regular inner class
class outer {
private double i =10.5;
private static String str =“hello”;
class inner {
int j;
public void display(){
j =5;
System.out.println(“j = “+j);
System.out.println(“i = “+i);
System.out.println(“str = “+str);
}
}
}
public class InnerClass {
public static void main(String[] args){
outer outobj =new outer();
outer.inner innobj = outobj.new inner();
innobj.display();
}
}
Output : j = 5
i = 10.5
str = hello
Explanation: When you compile this file, three class files will be created: InnerClass.class, Outer.class and Outer$Inner.class
The following points should be kept in mind while working with regular inner class.
• The inner class cannot have the same name as the enclosing class.
• There can be multiple inner classes in the same enclosing class.
• In addition to access specifiers, inner classes can also be final or abstract.
• Although inner classes may access static fields, methods or classes (except for constant fields that can be declared both static and final) they may not declare static members.
• An inner class can be extended just as the enclosing class.
• Within the enclosing class, you can instantiate the inner class using only the name of the inner class,
Inner innObj = new Inner();
Within the inner class, the keyword this holds a reference to the inner class instance. To reference the outer class using this, precede the keyword this with the outer class name. For example Outer.this.
Local Inner Class
A local inner class or simply a local class is a inner class that is declared inside a method or constructor or initialization block of the enclosing class. Like regular inner classes, the local classes are associated with a containing instance and can access any member, including the private members of the enclosing class. In addition, it can also access local variables in the method and parameters passed to the method only if the variables are declared final. Just like local variables, the inner class cannot be accessed outside the code block. It is useful when a computation in a method requires the use of specialized class that is not used elsewhere. The following program shows the use of local variable.
//use of Local class
class Outer {
private double i =10.5;
private static String str =“hello”;
public void display(){
class inner {
public void outerInfo(){
System.out.println(“i = “+i);
System.out.println(“str = “+str);
}
}
inner innobj =new inner();
innobj.outerInfo();
}
}
public class LocalClass {
public static void main(String[] args){
Outer outobj =new Outer();
outobj.display();
}
}
Output : i = 10.5
str = hello
The following points should be kept in mind while working with local inner classes.
• A local inner class cannot be declared public, private, protected or static.
• It cannot contain static fields, methods or classes (with an exception of constant fields that can be declared both static and final).
• It cannot have the same name as any of its enclosing class(es).
• In order to use local class, you must instantiate it and that instantiation must happen in the same method but after the class definition.
• It can access final variables but cannot access local variables.
Anonymous Inner Classes
Anonymous inner classes are the local inner classes that are declared without a name. All of the code for the anonymous class is coded within the method where we need to create an instance of the anonymous class. Since anonymous inner class do not have a name so you cannot use the new keyword in the usual way to create an instance of the class. In fact, anonymous inner classes are declared and instantiated at the same time. The most common place to see the use of anonymous inner classes is while handling Swing GUI controls.
//use of Anonymous class
class Outer {
private double i =10.5;
private static String str =“hello”;
public void display() {
Object obj =newObject() {
publicString toString() {
return(“I am Anonymous class”);
}
};
System.out.println(“i= “+i);
System.out.println(“str = “+str);
System.out.println(obj.toString());
}
}
public class AnonymousClass {
public static void main(String[] args){
Outer outobj =new Outer();
outobj.display();
}
}
Output : i = 10.5
str = hello
I am Anonymous class
Explanation: When this program is compiled, there classes AnonymousClass.class, Outer.class and Outer$1.class are created. This numbers is incremented for each anonymous class created by the compiler. In this program,
new Object () {………….. }
declares and instantiates an anonymous class. The new keyword is followed by the name of the class that specifies the type of the object created from anonymous class. It is followed by empty parentheses, which indicates no argument is passed to the constructor of anonymous class. It is then followed by code of the class. An assignment statement can use a anonymous class as shown in the example. In that case, anonymous class body is followed by a semicolon that marks the end of assignment statement. The semicolon is part of an assignment statement, not the anonymous class.
The following points should be kept in mind while working with anonymous inner classes.
• Anonymous inner class cannot have explicit constructors because they have no name to give to the constructor.
• It cannot be public, protected, private or static.
• It cannot either extend a class or implement an interface.
• Anonymous innerclass type must be either a subclass of the named type or an implementation of the named interface.
• It cannot access static fields, methods or classes (with an exception that constant fields can be declared both static and final).
• It should be used when only one instance of class is needed and body of the class is very short.
Static Nested Class
A static nested class or a top-level class is a class that is declared inside another class with a static modifier. Like static methods, a static nested class can only refer directly to static members of the enclosing classes, even if those members are private.
The basic structure of creating a static nested class is as follows,
public class OuterClassName {
public static class InnerClassName {
// body of static nested class
}// More members of outside class
}
Nested classes are generally made static when they have a strong relationship with the enclosing class, but their existence is independent of an instance of the enclosing class. Unlike inner classes, you can instantiate the static nested class even if you have not instantiated the outer class. For example:
OuterClassName.innerClassName = new OuterClassName.lnnerClassName();
The following program demonstrates the use of static nested class.
//use of Local class
class Outer {
private double i = 10.5;
private static String str = “hello”;
static class inner {
int j;
public void display() {
System.out.println(“j = “ +j);
//System.out.println(“i = ” +i); Illegal statement
System.out.println(“str = “+str);
}
}
}
public class StaticClass {
public static void main(String[] args) {
Outer.inner innobj = new Outer.inner();
innobj.display();
}
}
Output : j = 5
str = hello
Explanation: As static keyword is used in the innerclass so it is a static class. The str variable is declared static so it can be accessed in the static class. The variable i is not declared static so it cannot be accessed in the class.