Por que é prático.
Muitas vezes o código do corpo da interface é muito simples, e seria um desperdício de tempo (e de criatividade para nomes) criamos uma classe somente para isso.
Por exemplo, para escrever numa caixa de texto, a partir de outra thread, devemos empilhar esse pedido na fila de mensagens da AWT. Para fazer isso, chamamos o método invokeLater(Runnable r) da classe EventQueue.
O comando que queremos colocar lá é muito simples. É muito melhor fazer isso:
EventQueue.invokeLater(new Runnable() {
public void run() {
myText.setText("Vinicius");
});
Do que:
class TextUpdater implements Runnable() {
public void run() {
myText.setText("Vinicius");
});
EventQueue.invokeLater(new TextUpdater());
Esse exemplo não deixa tão claro a desvantagem do segundo caso. Imagine que você tenha um arquivo grande, ou que sua classe TextUpdater seja pública e esteja implementada em outro lugar. Quando você estiver analisando o código, deverá se deslocar sabe Deus para onde para localizar o que o bendito TextUpdater faz. Enquanto que no caso da InnerClass anônima, o código estará exatamente no ponto onde o método será invocado.