37
Classes Internas Raphael Marques

Classes Internas

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Classes Internas

Classes Internas

Raphael Marques

Page 2: Classes Internas

Classes Internas

• Tem gerado relações de amor e ódio desde sua introdução na versão 1.1

• Permite criar uma classe dentro de outra

• Uma classe é um MEMBRO de outra classe (como campos e métodos)

• Na prova geralmente são utilizadas em exemplos sobre outros tópicos

Page 3: Classes Internas

Classes Internas

• Podem acessar todos os membros da classe externa, mesmo os private

• Isso não quebra o encapsulamento

• Classe interna regular:– Não é static

– Não é local a um método

– Não é anônima

Page 4: Classes Internas

Classes Internas

class MyOuter {class MyInner {}

}

%javac MyOuter.java

MyOuter.classMyOuter$MyInner.class

%java MyOuter$MyInner

Page 5: Classes Internas

Classes Internas

class MyOuter {class MyInner {}

}

%javac MyOuter.java

MyOuter.classMyOuter$MyInner.class

%java MyOuter$MyInner → ERRO

Page 6: Classes Internas

Classes Internas

• %java MyOuter$MyInner → ERRO

• Uma classe interna regular não pode ter nenhuma declaração static

• Lembrando: uma classe interna regular não é static

Page 7: Classes Internas

Classes Internas

class MyOuter{private int x = 7;

class MyInner{public void seeOuter(){

System.out.println(“x: ”+x);}

}}

Page 8: Classes Internas

Classes Internas

• Para instanciar uma classe interna, é preciso uma instância da classe externa

Page 9: Classes Internas

Classes Internas

class MyOuter{private int x = 7;

public void makeInner(){MyInner in = new MyInner();in.seeOuter();

}

class MyInner{public void seeOuter(){

System.out.println(“x: ”+x);}

}}

Page 10: Classes Internas

Classes Internas

• MyInner in = new MyInner();

• Só é possível porque não existe nenhuma outra classe chamada MyInner acessível

• E como acessar a classe interna se ela precisa de uma instancia da classe externa?

Page 11: Classes Internas

Classes Internas

public static void main(String[] args){MyOuter outer = new MyOuter();MyOuter.MyInner inner = mo.new MyInner();inner.seeOuter();

}

public static void main(String[] args){MyOuter.MyInner inner = new MyOuter().new MyInner();inner.seeOuter();

}

Page 12: Classes Internas

Classes Internas

• Regras para utilização:

– Use MyInner dentro da classe externa

– Use MyOuter.MyInner fora da classe externa

– Use MyInner fora da classe externa se você já tem uma instância da classe externa

Page 13: Classes Internas

Classes Internas

public static void main(String[] args){

Outer outer = new Outer();

outer.new Inner();

outer.new Outer.Inner();

}

Page 14: Classes Internas

Classes Internas

public static void main(String[] args){

Outer outer = new Outer();

outer.new Inner(); → LEGAL

outer.new Outer.Inner(); → ILEGAL

}

Page 15: Classes Internas

Classes Internas

class MyOuter{

class MyInner{}

void makeInner(){

MyInner a = new MyInner();

MyInner b = this.new MyInner();

}

}

Page 16: Classes Internas

Classes Internas

• E o this?

• O this refere-se ao objeto da classe interna

• Outer.this refere-se ao objeto da classe externa

Page 17: Classes Internas

Classes Internas

public class Outer{private int x = 7;public class Inner{

private int x = 5;public void doSomething(){

...println(this.getClass());

...println(Outer.this.getClass());

...println(x);

...println(this.x);

...println(Outer.this.x);}

}}...new Outer().new Inner(). doSomething();

Page 18: Classes Internas

Classes Internas

public class Outer{private int x = 7;public class Inner{

private int x = 5;public void doSomething(){

...println(this.getClass()); → class Outer$Inner

...println(Outer.this.getClass()); → class Outer

...println(x); → 5

...println(this.x); → 5

...println(Outer.this.x); → 7}

}}...new Outer().new Inner(). doSomething();

Page 19: Classes Internas

Classes Internas

• Modificadores aplicáveis a classes internas:– final

– abstract

– public

– private

– protected

– strictfp

– static• a classe interna vira classe aninhada

• nested class

Page 20: Classes Internas

Classes Internas Locais a Métodos

public void m(){class Inner{

public void doSomething(){System.out.println("x:"+x);

}}new Inner().doSomething();

}

Gera: Outer.class e Outer$1Inner.class

Page 21: Classes Internas

Classes Internas Locais a Métodos

public static void m(){class Inner{

public void doSomething(){System.out.println("x:"+x);

}}new Inner().doSomething();

}

Gera: Outer.class e Outer$1Inner.class

Page 22: Classes Internas

Classes Internas Locais a Métodos

public static void m(){class Inner{

public void doSomething(){System.out.println("x:"+x); → ILEGAL

}}new Inner().doSomething();

}

Gera: Outer.class e Outer$1Inner.class

Page 23: Classes Internas

Classes Internas Locais a Métodos

public class Outer{public void m1(){

class Inner{}}public void m2(){

class Inner{}}

}

Gera: Outer.class, Outer$1Inner.class e Outer$1Inner.class

Page 24: Classes Internas

Classes Internas Locais a Métodos

public void m(){class Inner{}Inner inner = new Inner(); → LEGAL

}

public void m(){Inner inner = new Inner(); → ILEGALclass Inner{}

}

Page 25: Classes Internas

Classes Internas Locais a Métodos

• Uma classe interna local não pode usar as variáveis locais do método em que a classe interna está.

public class Outer{

void doSomething(){

int x = 0;

class Inner{

public void seeOuter(){

System.out.println(x); → ILEGAL

}

}

}

}

Page 26: Classes Internas

Classes Internas Locais a Métodos

• Porque?

– A variável local ao método só existe durante a execução do método

– Depois que o método termina a variável vira história

– Mas a referência ao objeto da classe interna pode se manter na memória

• Solução:

– Marcar a variável local como final

– É uma exigência do compilador

Page 27: Classes Internas

Classes Internas Locais a Métodos

• Só podem receber os modificadores:

– final

– abstract

Page 28: Classes Internas

Classes Internas Anônimas

class Popcorn {public void pop() {

System.out.println("popcorn");}

}

class Food {Popcorn p = new Popcorn() {

public void pop() {System.out.println("anonymous popcorn");

}};

}

Page 29: Classes Internas

Classes Internas Anônimas

Popcorn p = new Popcorn() { ... }

• O campo p da classe Food não faz referência à um objeto da classe Popcorn, mas sim a um objeto da subclasse anônima de Popcorn.

• Pode ser utilizado para estender superclasses ou implementar UMA interface

• O construtor usado deve existir na superclasse

• É possível declarar construtores em classes anônimas?

Page 30: Classes Internas

Classes Internas Anônimas

Popcorn p = new Popcorn();

– Objeto da classe Popcorn

Popcorn p = new Popcorn() {

public void pop() {...}

};

– Objeto da subclasse anônima de Popcorn

– Sobrescrevendo o método pop()

Page 31: Classes Internas

Classes Internas Anônimas

Popcorn p = new Popcorn();

– Objeto da classe Popcorn

Popcorn p = new Popcorn() {

public void pop() {...}

}; ← ← ← ← ← ← ← ← ← ← ← ← ←

– Objeto da subclasse anônima de Popcorn

– Sobrescrevendo o método pop()

Page 32: Classes Internas

Classes Internas Anônimas

Popcorn p = new Popcorn() {

public void pop() {...}

public void something() {...}

};

O segundo método não estará acessível na referência p

Page 33: Classes Internas

Classes Internas Anônimas

• Cuidado!

Runnable r = new Runnable(); → ILEGAL

Runnable r = new Runnable(){

public void run(){ }

}; → LEGAL

Page 34: Classes Internas

Classes Internas Anônimas como Parâmetro

System.out.println(

new Popcorn(){

public String toString(){

return “new poporn”;

}

}

);

→“new popcorn”

Page 35: Classes Internas

Classes Estáticas Aninhadas

• São classes internas estáticas

– Não são classes internas pela definição

• A classe interna pode ser acessada sem precisar de uma instancia da classe externa

Page 36: Classes Internas

Classes Estáticas Aninhadas

public class Outer{public static class Nest {}public static void main(String[] args){

Nest n = new Nest();}

}...public static void main(String[] args){

Outer.Nest n = new Outer.Nest();}

Page 37: Classes Internas

Classes Internas

• Cuidado com a sintaxe estranha

• Saiba as características de classes internas, locais a métodos, e classes aninhadas

• Não esqueça do ; quando criar uma classe anônima atribuindo a uma referência