I want this article to be the most simple yet complete article about inner classes in Java. As a consequence I shall divide it in two posts, the first one being a short fundamental introduction where I’ll show the fastest way to write inner classes, and the second one being an advanced discussion about all aspects concerning inner classes, their philosophy and all their practical uses. The knowledge in this article targets Java 5 (Tiger).
To begin with, let me mention there are four kinds of inner classes, namely:
- inner class
- method inner class (method local class)
- anonymous inner class (call it anonymous class)
- static inner class (nested class) – tratate in partea a 2-a a articolului
In Java, all these are inner classes.
There are many purposes and uses they have, but using them outside these can be considered evil and is not indicated. The need to use an inner class springs when a design issue rises: how can we create a class that is a “friend” (actual C++ terminology) of our Foo class? Of course, we make up an inner class, but this inner class is intimate to our Foo class and can access even private members of Foo. From outside Foo (also known as the containing or the external class), the inner class cannot be used (or actually shouldn’t be used) unless through an instance of the external class (Foo in our case).
An inner class is declared like this:
class InnerClass {
Simple, right? Also from this example we may see that InnerClass may access any member of ExternalClass as if it were its own. This is reciprocally valid.
An inner class may not be statically initialized, only in an instance of the external class and cannot have static members (since it must be tied to an instance of that class), but it can be instantiated from outside the external class in the following way:
Maybe it’s not awkward, but in any case it’s a construct that we shall never use anywhere else in Java. So, please don’t try to generalize it, rather take it as it is since it’s quite intuitive, natural and self-explanatory.
In order to access an instance of an inner class from within we shall use this keyword just like you might have expected, and in order to access a member belonging to the external class we do as if it were part of the inner class. But there is a single exception: to access the this of the external class one must write ExternalClass.this. That is we prefix this with the name of the external class. It’s a little weird, I know, but again don’t generalize this construct since this is the only time use prefix this with anything in Java.
A method local class has visibility only in the declaring method, as if it were a local variable… if you like me may just call it a local type or local class. Besides this, it behaves just like regular inner classes with two exceptions (of course): it cannot be instantiated from outside the containing method (obviously not from outside the containing class) and it cannot access any local variables declared in the containing method unless they are declared final. Of course the syntax is just as expected:
public void ContainerMethod(){
class InnerClass {
System.out.println(b);
InnerClass instance = new InnerClass();
Instance.access();
An anonymous class, is rather an object and a class at the same time. They are the most frequently used and of course they provide the only solution for an elegant event handling mechanism in Java. These along with interfaces go together as milk with honey. Of course, don’t overuse.
Syntax:
An anonymous class always extends something, or better yet any class in Java extends something and if it doesn’t do so explicitly then it does implicitly extend Object. Same goes for our anonymous class except that an anonymous class we always do it the explicit way (follow the syntax). Since an anonymous class bears no name we cannot instantiate it (again, the syntax for creating an object requires its type) unless one single object of it is automatically provided. As a consequence we may not reuse this class as probably this was the desire to begin with. In our situation we create an object of type Object extended with what’s in between the {,}. That is we extend class Object on the spot and also get an object of the newly obtained anonymous type. The particular instance is stored then in a reference of type Object and the only way in which we can take an advantage of this extension is polymorphism. To be more precise we should modify the implementation of a method but there’s no point in adding new methods since they are not visible (maybe they are with Reflection).
So, an anonymous class may implement an interface (the only reason why an interface can’t be instantiated is because it’s methods are abstract and provide no implementation). If we extend an interface with an anonymous class and we implement all its abstract methods, we obtain a valid implementation object and so we may use it instead of Object
Yes, now you understand that interfaces and anonymous classes go together like … well, you know what.
Here the article ends and I invite you to read the second part (when it will appear soon) about the more advanced aspects of inner classes.
