I was dealing with some legacy code at work and came across some Java inner classes. Looking at those inner classes I realised that they had a bad feel to them; they break some of the SOLID principles.
The main problem lies with non-static inner classes. In the case of a static inner class why not just move the code out into a separate file? Some people argue that inner classes help to keep related things close together but it seems to go against the spirit of the SOLID principles. And other things aside, they completely break encapsulation.
Single Responsibility Principle
The single responsibility principle is about keeping things simple and manageable. However, inner classes add a highly (sometimes very highly) coupled added responsibility to a class. By adding the inner class complexity increases and testing is harder. In the case of a static inner class the two classes may be testable independently. However non-static inner classes can't be tested as an individual unit.
Dependency Inversion Principle
Again non-static inner classes break this principle: they are tightly coupled and depend on each other's implementation. As I mentioned above this makes testing the two classes in isolation impossible.
Open/Close, Liskov Substitution and Interface Segregation Principles
These principles relate more to the implementation specifics of classes. While the relationship between an inner class an its enclosing class doesn't explicitly break the principles, it must make it harder to write an outer class that complies with the principles.
Anonymous Inner Classes
In most cases anonymous inner classes fall into a slightly different category. Especially in Swing, anonymous inner classes are an important feature required to create clean UI code. However they are very much the exception to the norm. These sorts of small event handling classes are really just a poor substitute for language level events and delegates (such as those in the .net framework).
The more I consider Java inner classes the more I am inclined to avoid them. Looking at them in terms of the SOLID principles helps to outline why they can seem to complicate a class and related class design.