quinta-feira, 22 de maio de 2014

Classes Anônimas em Java

Em alguns momentos precisamos implementar alguma coisa pequena e simples, de forma “privada” e obedecendo alguma interface já definida, acho que esse é o melhor momento de se utilizar as classes anônimas.
O código abaixo vai utilizar uma classe anônima para implementar a interface Runnable, esta interface pode ser utilizada para definir a ação de uma Thread.
import java.lang.Thread;
import java.lang.Runnable;

public class Blog{

    public static void main(String... args) throws Exception{
        
        Runnable runnable = new Runnable(){
            @Override
            public void run(){
                System.out.println(this.getClass());
            }
        };

        for(int i=0;i<5;i++){
            new Thread(runnable).start();
        }
    }
}

Algo muito interessante das classes anônimas, é que sempre é guardado uma referencia da instância do objeto que a criou, assim é possível acessar essa instância de dentro da classe anônima. Para diferenciar de qual instância o this está se referenciando é utilizado o nome da classe, como no exemplo abaixo.

import java.lang.Runnable;

public class Blog{

    private int cont =0;

    public Blog(){

    }

    public Runnable constroiClasseAnonima(){
        return new Runnable(){
            private int cont = 0;
            @Override
            public void run(){
                System.out.println(
                    this.getClass()+":"+this.cont
                );
                System.out.println(
                    Blog.this.getClass()+":"+Blog.this.cont
                );
                this.cont++;
                Blog.this.cont++;
            }
        };
    }

    public static void main(String... args){
        Blog blog = new Blog();
        for(int i=0;i<5;i++){
            blog.constroiClasseAnonima().run();
        }
    }
   
}

Reparem que a classe anônima teve total acesso aos atributos privados da classe responsável por sua instanciação.
O NetBeans por padrão cria classes anônimas para responder aos eventos gerados por botões implementado a interface ActionListener, de forma semelhante ao exemplo abaixo.

import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.FlowLayout;

public class Blog extends JFrame{

    private JButton btOi = new JButton("Diga oi!");

    public Blog(){
        super("Programando no Aquário");
        this.setLayout(new FlowLayout());
        this.add(btOi);
        //ajusta tamanho da janela
        this.pack();
        //posiciona do centro da tela
        this.setLocationRelativeTo(null);
        //finaliza ao fechar janela
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        btOi.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent event){
                Blog.this.dizOiJanela();    
            }
        });

        btOi.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent event){
                Blog.this.dizOiTerminal();    
            }
        });
    }

    private void dizOiJanela(){
        JOptionPane.showMessageDialog(null,"Olá Mundo!!!");
    }

    private void dizOiTerminal(){
        System.out.println("Olá Mundo!!!");
    }

    public static void main(String... args){
        new Blog().setVisible(true);
    }
   
}

É possível também criar classes anônimas de classes abstratas ou até mesmo concretas, a sintaxe é a mesma só que invés de implementar métodos de uma interface, você terá que implementar métodos abstratos de uma classe abstrata ou sobrescrever métodos de uma classe qualquer.

Segue outro exemplo utilizando Thread, porém desta vez é sobrescrito o método run da própria classe Thread.
import java.lang.Thread;

public class Blog{

    public static void main(String... args) throws Exception{
        
        Thread thread = new Thread(){
            @Override
            public void run(){
                System.out.println(this.getClass());
            }
        };

        thread.start();
    }
}

Obrigado!

Um comentário :