Inner classes allow defining a class within another class. There are several types of inner classes: static nested classes, anonymous inner classes, and local inner classes. Inner classes can access members of the outer class and the outer class can return inner class instances implementing an interface. The main uses of inner classes are event handlers, callbacks, and upcasting inner classes to interfaces or superclasses.