Classes internas
Classes internas
É possível definir uma classe dentro de outra classe; isso é o que chamamos de classe interna:
public class ClasseExterna {
int x;
class ClasseInterna {
int y;
}
}
Por que usar classes internas
Possivelmente trata-se de uma classe que só faz sentido em conjunto com a classe externa.
Classe interna
Em geral, um objeto de uma classe interna precisa estar associado a um objeto da classe externa, e tem acesso a todos os seus membros (inclusive os privados).
class ClasseExterna {
private int x;
public ClasseExterna(int valor) {
x = valor;
}
public void roda() {
ClasseInterna ci = new ClasseInterna();
ci.imprimeX();
}
public class ClasseInterna {
int y;
public void imprimeX() {
System.out.println(x);
}
}
}
public class Main {
public static void main(String[] args) {
ClasseExterna ce = new ClasseExterna(5);
ce.roda();
}
}
Instanciando classe interna fora da classe externa
Nesse caso, você deve prefixar o new
com o objeto da classe externa ao qual o novo objeto será vinculado.
public class Main {
public static void main(String[] args) {
ClasseExterna ce = new ClasseExterna(5);
ClasseInterna ci = ce.new ClasseInterna();
ci.imprimeX();
}
}
Modificadores
- A classe interna pode ter modificadores de visibilidade:
public
,protected
,private
ou nenhum (privado ao pacote). - A classe interna pode ser declarada com
static
caso ela não precise acessar nenhum membro da classe externa. Nesse caso, a classe interna pode ser instanciada mesmo sem uma instância da classe externa. - Você pode declarar uma classe interna dentro de um método!
Classes internas anônimas
Exemplo inicial:
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
new Exemplo().executa();
}
}
class Exemplo {
public void executa() {
// Usando impressora para imprimir um número
Impressora impressora = new Impressora();
impressora.accept(5);
// Usando impressora com forEach
List<Integer> list = Arrays.asList(3, 7, 5, 1);
list.forEach(impressora);
}
}
class Impressora implements Consumer<Integer> {
@Override
public void accept(Integer t) {
System.out.println(t);
}
}
Classes internas anônimas
Se você quer criar uma classe para instanciar uma única vez, você pode criar uma classe implicitamente.
class Exemplo {
public void executa() {
// Usando impressora com forEach
List<Integer> list = Arrays.asList(3, 7, 5, 1);
list.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer t) {
System.out.println(t);
}
});
}
}
Outro exemplo
public class Main extends JFrame {
public Main() {
JButton botao = new JButton("Confirmar");
add(botao);
pack();
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
botao.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(Main.this, "Confirmado");
}
});
}
public static void main(String[] args) {
new Main();
}
}
Uso do this
No exemplo anterior, note que, dentro da classe interna, this
refere-se ao objeto da classe interna. Se você quiser se referir ao objeto correspondete da classe externa, use NomeDaClasseExterna.this
.