37
Classes Internas Raphael Marques

Classes Internas

Embed Size (px)

DESCRIPTION

Slides sobre classes internas de Java

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 Internasclass MyOuter {

class MyInner {}}

%javac MyOuter.java

MyOuter.classMyOuter$MyInner.class

%java MyOuter$MyInner

Page 5: Classes Internas

Classes Internasclass 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 Internasclass 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 Internaspublic 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(); → LEGALouter.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 Internaspublic 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 Internaspublic 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étodospublic 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étodospublic 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étodospublic 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étodospublic 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ônimasclass 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ônimasPopcorn 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 Aninhadaspublic 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