A nested class is a class declared within another class. It’s a member of the enclosing class and so can be declared private
, public
, protected
or default.
A nested class can be static, inner, local or anonymous. The following sections try to clarify these sometimes-confusing terms.
Static Nested Classes
The two key things you must know about static nested classes are:
- They don’t have access to the non-static members of the enclosing class
- They are behaviorally like a top-level class that has been nested in another top-level class for packaging convenience
The following is an example of a static nested class, including how you can create an object of such a class (lines 15 and 23):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class EnclosingClass { int i; static int j; static class StaticNestedClass { void foo() { i++; // compiler error: access to non-static member of enclosing class j++; } } public void enclosingFoo() { // creation from the enclosing class StaticNestedClass snc = new StaticNestedClass(); snc.foo(); } } class Other { public void otherFoo() { // creation from outside the enclosing class EnclosingClass.StaticNestedClass snc = new EnclosingClass.StaticNestedClass(); } } |
Inner Classes (Non-Static Nested Classes)
Inner classes are the second category of nested classes. Again, there are two key things you must know about them:
- They have access to the members of the enclosing class (even private)
- Since they are associated with an instance (an object), they can’t define any static members themselves (except constant variables, i.e. primitive type or
String
, declaredfinal
and initialized with a compile-time constant expression)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public class EnclosingClass { private int i; class InnerClass { static int j; // compiler error: declaring static member that is not a constant static final int k = 5; void foo() { // An inner class have access to the enclosing class members i++; } } public void outerFoo() { // creation from the enclosing class InnerClass ic = new InnerClass(); } } class Other { public void otherFoo() { // creation from outside the enclosing class EnclosingClass.InnerClass ic = new EnclosingClass().new InnerClass(); } } |
There are two specialized types of inner classes:
- Local classes
- Anonymous classes
Local Classes
They are class declarations inside a block and:- They have access to local variables declared
final
- Inside static methods they can only refer to static members of the enclosing class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
class EnclosingClass { int a = 2; static int b = 3; // non-static method of the enclosing class void foo() { final int i = 1; int j = 2; class LocalClass { void localFoo() { // final variable "i" is accessible System.out.println(i); // compiler error: non-final "j" is not accessible j++; // members of enclosing class are accessible a++; b++; } } } // static method of the enclosing class static void staticFoo() { class LocalClass { void localFoo() { // non-static member of enclosing class is not accessible a++; // static member of enclosing class is accessible b++; } } } } |
Anonymous Classes
They are expressions of two kinds, either implementing an interface (new InterfaceName(){ … }
) or extending another class (new ClassName(args) { … }
). In both cases:
- They have access to local variables declared
final
- They can’t declare constructors
The following is an example of an anonymous class extending the EventHandler
class:
1 2 3 4 5 6 7 |
EventHandler h = new EventHandler<ActionEvent>() { public void handle(ActionEvent event) { System.out.println("Anonymous!"); } }); |