There are two kinds of inner classes. Regardless of which you use, they are typically constructed by the owning outer class when asked for (see pattern "Factory Method").

The original driver for this monstrosity was (AFAIK) iterators on collections. You need a different implementation for an iterator depending on the kind of datastructure. So an iterator for an array is radically different from one that works on a binary tree. Furthermore, the iterator typically needs access to the guts of the collection that it is iterating. So the approach used was:


class LinkedList implements List
{
int _count;
Node _head;

class ListIterator implements Iterator
{
Node _current;
public boolean hasNext() { return _current._next == _head; }
}
public Iterator iterator() { return new ListIterator(); }
...
}

ListIterator is an inner class - notice that it can see the _head ivar of its owner instance. This is because Java compiler magic inserts a hidden reference to the creating instance (call it "that") and then fixes up all references to the enclosing class's ivars to actually be something like that._head. If you decompile a .class file that has an inner class defined, you'll note a bunch of accessors defined that start with $. These are generated to provide sneaky access to the innards of the owning object - effectively replicating the "friend" declaration from C++.

I dislike this mess because it ends up with hidden costs - the inner class has more storage and the outer class has more methods than one would think from viewing the source code. Furthermore, you don't always need the "that" pointer or access to the enclosing object. Consider the Node structure in the above linked list. You'd like to make that an inner class too. But penalizing it with a "that" pointer is a waste of space. Thus we find YET ANOTHER use for the keyword "static".

class LinkedList implements List
{
static class Node { public Node _next; public Object _value; } // just a struct

}

which tells the compiler that we won't be accessing our containing object, thanks.

I nearly always make my inner classes static as I dislike compiler magic.