Classes Internas e Anônimas
Prof. Ricardo Linden
Classes Internas e Anônimas
1
Classes Internas
Classes Internas são classes dentro de classes.
Declaramos
classes exatamente como fazíamos
antes, mas agora ela está dentro do corpo de outra
classe
Consequentemente dentro do arquivo .java desta
outra classe).
As suas regras de acesso são um pouquinho
diferentes.
O uso mais comum das classes internas é para lidar
com eventos, como veremos mais a frente.
Classes Internas e Anônimas
2
Como declarar?
Uma classe aninhada (tipo de classe internas) é
declarada dentro de uma classe existente
Exemplo:
public class MyRegularClass
{
…….
class myInnerClass
{ ….
}
}
Classes Internas e Anônimas
3
Classes Internas
Os objetos das classes internas são associados com objetos das
classes envoltórias
Para criar um objeto de uma classe interna é necessário criar
primeiro um objeto da classe externa.
Exemplo
BankAccount account = new BankAccount();
BankAccount.money amount = account.new Money(“41.99”);
System.out.println(amount.getAmount());
Classes Internas e Anônimas
4
Regras de Acesso
Uma classe aninhada tem acesso total aos campos e
métodos da classe que a envolve, incluindo aqueles
de acesso privado.
De acordo com a Sun, isto não quebra o conceito de
do acesso privado, já que a classe aninhada também
“pertence” à classe que a envolve.
Classes Internas e Anônimas
5
Modificadores de Acesso
Classes internas pode ter modificadores:
– public
– protected
– private
– Ou ter acesso package-level (sem modifiadores)
Classes Internas e Anônimas
6
Static Não-Static
Uma classe aninhada pode ser declarada como static
ou não.
Se ela não for static, é chamada de classe interna.
Se for static, é chamada de classe estática aninhada.
Uma classe estática aninhada está associada à classe
que a envolve e não pode referenciar nenhuma das
variáveis de instância.
Entretanto, elas podem acessar todos os membros
(variáveis e métodos) estáticos da classe envoltória.
É como se fosse um método estático.
Classes Internas e Anônimas
7
Classes Aninhadas Estáticas
Exemplo:
public abstract class Elipse2D {
…
public static class Float extends Elipse2D {
…
}
}
A referência a elas é feita usando o nome da classe
envoltória. Exemplo:
new Elipse2D.Float (10., 20., 30., 40.)
Classes Internas e Anônimas
8
Classes Aninhadas Estáticas
Uma classe aninha estática não tem nenhuma
relação com os objetos da classe envoltória
– Instâncias das variáveis não podem ser
referenciadas.
– Métodos não estáticos não podem ser invocados
Classes Internas e Anônimas
9
Convenções de Chamada
Para chamar um método de uma classe estática
aninhada na classe envoltória:
– InnerClassName.staticMethodName
Para referenciar uma variáve stática de uma classe
estática aninhada:
– InnerClassName.staticVariableName
Classes Internas e Anônimas
10
Classes Internas
Uma
instância de uma classe interna existe
efetivamente dentro de uma instância da classe que
a envolve.
Instância da OuterClass
Instância da InnerClass
Classes Internas e Anônimas
11
Classes Internas
Se você declarar new myInnerClass() em algum
ponto no código, um novo objeto será criado com
acesso a todas as variáveis de instância ao objeto
que o envolve.
Ele será declarado com acesso a todas as variáveis
internas da classe que o envolve.
Classes Internas e Anônimas
12
Exemplo Simples
public class FixedStack {
Object array[]; int top = 0;
FixedStack(int limit) {array = new Object(limit);}
public void push(Object item) { array[top++] = item; }
public boolean isEmpty() { return top == 0; }
class Enumerator implements java.util.Enumeration {
int count = top;
public boolean hasNoreElements() { return count > 0; }
public Object nextElement() {
if (count == 0)
throw new NoSuchElementException(“FixedStack”);
return array[--count];
}
}
public java.util.Enumeration elements() {
return new Enumeration(); }
}
Classes Internas e Anônimas
13
Comentários sobre exemplo
Neste caso, a interface java.util.Enumeration
é indispensável para o funcionamento da classe
interna.
A instância que contém um Enumerator é da classe
FixedStack.
– Para se referir a ela, use FixedStack.this
Em uma classe estática aninhada, é proibido se
referir à instância FixedStack.this
Classes Internas e Anônimas
14
Exemplo
public class TestInstanceInnerClass {
private JButton button1, button2;
class Listener implements ActionListener {
public void actionPerformed (
ActionEvent evt){
Object src = evt.getSource();
if (src == button1)
System.out.println ("One");
else if (src == button2)
System.out.println ("Two");
else if (src == button3)
System.out.println ("Three");
}
}
Classes Internas e Anônimas
15
Exemplo (continuação)
public TestInstanceInnerClass() {
JFrame frame;
button1 = new JButton ("One");
button2 = new JButton ("Two");
frame = new JFrame ("Test Instance Class");
Container cp = frame.getContentPane();
cp.add ("North", button1);
cp.add ("Center", button2);
Listener lstnr = new Listener();
button1.addActionListener (lstnr);
button2.addActionListener (lstnr);
frame.setSize(175, 150);
frame.setVisible (true);
}
public static void main (String[] args) {
new TestInstanceInnerClass();
}
}
Classes Internas e Anônimas
16
Classes Internas Locais
São definidas dentro de um método ou outro bloco
(como um if ou um for)
Só podem ser referenciadas dentro daquele bloco.
Podem referenciar:
– variáveis de instância da classe que as envolve
– variáveis locais final do bloco que as envolve.
Classes Internas e Anônimas
17
Exemplo
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestLocalInnerClass {
public static void main (String[] args) {
JFrame frame;
final JButton button1, button2;
button1 = new JButton ("One");
button2 = new JButton ("Two");
frame = new JFrame ("Test Local Class");
Container cp = frame.getContentPane();
cp.add ("North", button1);
cp.add ("Center", button2);
frame.setSize(175, 150);
Classes Internas e Anônimas
18
Exemplo (continuação)
class Listener implements ActionListener {
public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
if (src == button1)
System.out.println (”Um");
else if (src == button2)
System.out.println ("Two");
}
}
Listener lstnr = new Listener();
button1.addActionListener (lstnr);
button2.addActionListener (lstnr);
frame.setVisible (true);
}
}
Classes Internas e Anônimas
19
Observações...
É possível ter classes internas às classes internas.
Exemplo: Classe A tem classe interna pública B que
tem uma classe interna pública B C:
A.aObject = new A( );
A.B bObject = aObject.new B( );
A.B.C cObject = bObject.new C( )
Classes Internas e Anônimas
20
Regras de herança
Seja OuterClass que contém uma classe interna InnerClass.
Logo:
– Se DerivedClass é uma subclasse de OuterClass, então
DerivedClass também tem InnerClass como classe interna
– Não é possível sobrepor a definição de InnerClass em
DerivedClass.
– InnerClass pode extender uma classe.
– OuterClass pode externder uma classe diferente de
InnerClass
Classes Internas e Anônimas
21
Classes Anônimas
Em algum momento podemos não nos importar com
o nome das variáveis.
Se não quisermos dar nome às nossas classes,
estaremos criando classes anônimas.
Classes anônimas são classes que são declaradas
“on-the-fly”, isto é, onde são necessárias, dentro de
um bloco de código.
Classes Internas e Anônimas
22
Classes Anônimas
Nós sabemos que não vamos precisar de outra
instância dela após, logo não temos necessidade de
dar-lhe um nome que permita o acesso posterior.
Estas classes não pode ter construtores
– não têm nome para colocar depois do new!
Classes Internas e Anônimas
23
Exemplo
MeuBotao.addActionListener (new ActionListener(){
public void actionPerformed (ActionEvent evt){
:
}
});
Nós sabemos que o ActionListener deste botão é
muito específico e não será usado por mais ninguém.
Logo, podemos declará-lo imediatamente.
Não se preocupem com os conceitos de programação
gráfica. Nós vamos discuti-los com detalhes depois.
Note que nós não definimos um construtor, só o
método que nos interessava naquele momento.
Classes Internas e Anônimas
24
Quando usar classes anônimas
Crie classes anônimas apenas quando suas classes forem muito
pequenas (um ou dois métodos).
Mais que isto e seu programa será ilegível.
Eventos de botões, que são muito específicos, são bons
candidatos ao uso delas.
Mantenha-as curtas: já que você tem acesso a todos os
métodos da classe envoltória, mantenha o grosso do código
dentro dela.
Classes Internas e Anônimas
25
Resultados da Compilação
Quando você compilar uma classe interna, você verá
no seu diretório um arquivo com o nome
OuterClass$InnerClass.class
Quando você compilar uma classe anônima, você
verá no seu diretório um arquivo chamado
OuterClass$n.class, onde n é um número inteiro
crescente.
Classes Internas e Anônimas
26
Questões de Implementação
Implementada
através de tradução para os mecanismos
habituais do Java
– A instância da classe envoltória é referenciada por this$0
– A variável local x da classe envoltória é referenciada por
val$x
– O compilador se encarrega de copiar os códigos de this$ e
todos val$ no momento da criação do objeto.
Referenciando:
– instância do objeto que contém classe: classe_env.this
Não pode conter variáveis estáticas
Quebram o conceito dos modificadores private e protected
Classes Internas e Anônimas
27