''Note: in this page, "inner classes" means "non-static inner classes".'' JavaIdiom: Inner classes should never be exposed in the PublicInterface of a class, because they make the interface ugly and inhibit refactorings later. This is an example of an inner class: package com.c2.foo; public class Outer { int x, y; public Outer(int x, int y) { this.x = x; this.y = y; } public int getBigger() { return (x > y) ? x : y; } // ... more methods & constructors public class Inner { int a, b; public Inner(int a) { this.a = a; this.b = Outer.this.x * 2; } // ... more methods and constructors } } This does several things: * Gives all instances of Inner a "magic" final reference to an instance of Outer, similar to the way methods have a magic hidden parameter of ''this''. * Puts Inner inside the namespace of Outer, so that its name is com.c2.foo.Outer.Inner (though it's actually mangled into com.c2.foo.Outer$Inner, if I recall correctly.) * Puts the associated Outer instance in the scope of methods on this. Without inner classes, this could be represented as public class Parent { int x, y; } public class Child { int a, b; private final Parent parent; // explicitly stored public Child(Parent parent, int a) { this.parent = parent; this.a = a; this.b = parent.x * 2; } } Relatively few Java programmers, including HighlyPaidConsultant''''''s, really understand how inner classes work, but they get by (mostly) by copying from the examples. It's arguable whether inner classes are a kludge or not -- certainly they are convenient for many situations, but other languages have more consistent and equally flexible solutions. In any case, inner classes should never be exposed in the public interface of the package. Here's why: * The syntax for constructing and using them when not in the scope of Outer is bizarre and ugly, and inconsistent with other syntax in the language. It consistently causes problems in understanding. Outer o = getSomeOuter(); Outer.Inner i = o.new Inner(3); // ... * Exposing the fact that certain classes are implemented as inners limits the possible future refactorings of the implementation. The inner must always be associated with a particular outer class, but if a normal association or containment relationship were used it could be refactored. For example, we could generalize the explicit implementation without affecting clients, but this is not possible with inner classes. public interface CareTaker { ... } public class Parent implements CareTaker { ... } public class Child { // ... private final CareTaker careTaker; public Child(CareTaker careTaker, int x) { this.careTaker = careTaker; // ... } } Inner classes have a perfectly appropriate place as SyntacticSugar for private implementations of public interfaces, but they should not be abused. Nested classes (aka static inner classes) and interfaces are less harmful, but still should be used in moderation. ---- Actually, a fair number of people understand inner classes. They're not that complicated an idea. The two final bullet points aren't parallel. "Bizarre and ugly" seems needlessly pejorative. And saying that public inner classes limit refactoring is confusing. More so than using a second "outer class" (e.g. another class, defined in a second .java file)? Of course not. So; we have two classes, working together to accomplish something. One of them is definitely outer. One of them may be inner or outer. The typical reason for making a class an inner class is something along the lines of "It's not a top level abstraction" or "instances of this really do have a very limited context in which they make sense. And that context includes having a pointer to (and being owned by) an instance of the outer class." Once you have one of these statements, maybe the second class should be an inner one. But what does this have to do with refactoring? I'm guessing some LawOfDemeter style argument could be made at some point. But ''never'' seems way too strong a statement. I've been using public inner classes to define complicated return values (ala UseObjectsToReturnMultipleValues or ResultObject) for some time now and it seems to result in a fairly pleasant code structure. WilliamGrosso ---- Here is another discussion about UsageOfInnerClasses ---- I find inner classes very useful in the form of inner interfaces. For instance, I have a static method findFirst that finds the first element of a Collection that matches a predicate. Obviously, I need some interface for predicates, but I'm not bold enough to write a top-level Predicate interface -- I just haven't thought it through deeply enough to do that. So I just put the interface into the same class as findFirst and can be confident that other people see that this interface is intended for a very limited purpose. -- MichaelSchuerig ---- Sometimes it makes sense to declare inner classes as public (but definitely static) for packaging convenience. There is an example of it in javax.swing.text.DefaultEditorKit. Tsolak Petrosian ---- I think events and listeners would be good candidates for static inner classes. For example, the java.awt.Component class could have had ComponentEvent and ComponentListener static inner classes, since their use is exclusively bound to the usage of Component. Chris Dailey Yes, but could those be private inner classes? (I'm not familiar with AWT.)