Accessing
an Inner Class from the Outside
If an inner class is declared with a public access modifier, it can be instantiated from outside the scope of its enclosing class. This is illustrated in the program shown here:
class Outer {
private int counter = 0;
public class Inner {
public void someMethod() {
counter++;
}
}
public int getCount() {
return counter;
}
}
public class InnerClassExample {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.someMethod();
System.out.println("Counter: " + outer.getCount());
inner.someMethod();
System.out.println("Counter: " + outer.getCount());
}
}
In
the application’s main method, the program creates an instance of the Outer class. To create an instance of the Inner class that is embedded in the definition of the Outer class, you use the following statement:
Outer.Inner inner = outer.new Inner();
Note that this statement uses the following syntax for a fully qualified name to create a variable of the Inner class type:
OuterClassName.InnerClassName
The new operator creates an instance of the Inner class. Once the program obtains an instance of the Inner class, it calls its someMethod twice and prints the value of the private variable counter in each case. Because a private variable cannot be accessed directly from outside the scope of the declaring class, the program uses the public getCount method to access this variable. If we run this application, we will see the following output:
Counter: 1
Counter: 2
Note that the value of the counter variable changes after each invocation of someMethod.
Accessing Shadowed Variables
When a variable declared within a certain scope (block, method, or inner class) has the same name as a variable declared in an outer scope, we say that the outer variable is shadowed. An inner class may declare a variable having the same name as the one defined in the outer class. The program here shows us how to differentiate between the shadowed and the original variables.
class Outer {
private int size = 10;
public class Inner {
private int size = 20;
public void someMethod(int size) {
System.out.println("Method parameter (size): " + size);
System.out.println("Inner size: " + this.size);
System.out.println("Outer size: " + Outer.this.size);
}
}
}
public class ShadowedVariableExample {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.someMethod(5);
}
}
The Outer class declares a field called size. The Inner class declares a field with the same name. The Inner class defines a method called someMethod. This method takes a local parameter having the name size. In the method implementation, we now have to differentiate between these three variables having the same name size. If we use the field name size as is, without any qualifier, as shown in the following statement, it will refer to the method argument:
System.out.println ("Method parameter (size): " + size);
If we use the qualifier this in front of the field name, it refers to the field declared in the current class field, as shown in the statement here:
System.out.println ("Inner size: " + this.size);
To access the size variable declared in the Outer class, we need to use the notation Outer.this.size. This is shown in the following program statement:
System.out.println ("Outer size: " + Outer.this.size);
To verify these statements, in the application’s main method, we invoke the someMethod method of the Inner class. The program output is shown here:
Method parameter (size): 5
Inner size: 20
Outer size: 10
We can compare the output with the values assigned to the three variables in the program code.
Few Important Points to Note
Here’s a summary of some important points on the use of inner classes:
•The name of the inner class must differ from the name of its enclosing outer class.
•When compile the outer class, the compiler generates a separate .class file for each of its inner classes. The name of the .class file is OuterClassName$InnerClassName.
•The inner class can use both the class and instance variables of enclosing classes and local variables of enclosing blocks.
•The inner class may be declared using any of the available access modifiers. A private inner class can only be accessed within the outer class scope.
•An inner class can be an interface. Another inner class then implements this interface.
•An inner class can be abstract.
•An inner class that is declared static automatically becomes a TopLevel class.
•We cannot declare a static member inside an inner class unless the inner class itself is declared static.
•An inner class that wants to use a static variable must be declared static.
•The static keyword can be applied to an inner class and not to an outer class.
Sushant Mishra
04-Apr-2017