O que significa uma regular inner-class com o modificador ‘final’ em sua declaração?

Post relacionado: Polimorfismo apenas para métodos de instância

Como se poderá observar nos testes 1 e 2 logo abaixo, foi possível escrever uma nova classe Inner a classe que estende a Outer (SpecificOuter) mesmo que a classe Inner contida na Outer estivesse marcada como final.

Teste 1)

 

class Outer {

public void doSomething(){

Inner i = new Inner();

}

 

/*

FINAL para classe significa que ela não pode ser extendida, mesmo que esta seja um MEMBRO de outra classe (como uma inner class).

 

O fato de termos declarado uma inner class como final não significa que em uma classe que extenda a outer class não possamos ter uma inner class declarada com o mesmo nome, mas sim, apenas que a inner class não poderá ser extendida por qualquer outra classe.

  • Para ver como extender uma inner class, veja abaixo: Teste 4
  • Para ver o efetivo uso de final (conforme descrito acima) veja abaixo:

*/

 

public final class Inner{

@Override

public String toString() {

return “Inner”;

}

}

 

@Override

public String toString() {

return “Outer”;

}

}

 

class SpecificOuter extends Outer{

@Override

public String toString() {

return “SpecificOuter”;

}

 

/*

Repare que ao declarar uma inner class com o mesmo nome da inner class da superclasse da outer class (Outer.Inner = SpecificOuter.Inner) não estamos sobrescrevendo-a. Cada outer class possui sua inner class. Da mesma forma funciona para variáveis de instância.

Veja em: Polimorfismo apenas para métodos de instância

*/

 

public class Inner {

@Override

public String toString() {

return “SpecificInner”;

}

}

}

 

public class OuterTest3 {

public static void main(String args[]){

Outer o = new SpecificOuter();

Outer.Inner i = o.new Inner(); // polimorfismo apenas para métodos de instância! Aqui será instanciada a inner da classe Outer, e não da SpecificOuter.

 

System.out.println(o);

System.out.println(i);

}

}

Output:

SpecificOuter

Inner

 

Teste 2)

 

Dadas as mesmas classes acima, vamos fazer o teste só que desta vez instanciando a classe Inner da Specific Outer.

 

public class OuterTest3 {

public static void main(String args[]){

SpecificOuter o = new SpecificOuter();

SpecificOuter.Inner i = o.new Inner();

 

System.out.println(o);

System.out.println(i);

}

}

Output:

SpecificOuter

SpecificInner

 

 

Teste 3)

Abaixo demonstraremos que por mais que as classes Outer e SpecificOuter tenham uma relação de herança, as classes Inner declaradas em cada uma das outer class nada tem a ver com a outra.

 

public class OuterTest3{

public static void main(String args[]){

Outer o = new SpecificOuter();

SpecificOuter.Inner i = o.new Inner();

 

System.out.println(o);

System.out.println(i);

}

}

Ao compilar este código (javac):

Teste.java:34: incompatible types

SpecificOuter.Inner i = o.new Inner();

^

required: SpecificOuter.Inner

found: Outer.Inner

1 error

Teste 4)

Abaixo será demonstrado como realizar herança de uma classe interna (inner class).

class Outer {

public void doSomething() {

Inner i = new Inner();

}

 

public class Inner {

@Override

public String toString() {

return Outer.this + “/Inner”;

}

}

 

@Override

public String toString() {

return “Outer”;

}

}

 

class Another extends Outer.Inner {

public Another() {

new Outer().super(); // “qualified superclass constructor invocation”

}

 

@Override

public String toString() {

return “AnotherClass”;

}

}

 

public class OuterTest4 {

public static void main(String args[]){

Outer.Inner i = new Outer().new Inner();

System.out.println(i);

 

Another a = new Another();

System.out.println(a);

}

}

Output:

Outer/Inner

AnotherClass

Teste 5)

Mostrando finalmente para que serve o keyword final para inner classes.

Abaixo, podemos concluir que o final na declaração de uma classe seja ela inner ou outer ou uma classe qualquer impede que a mesma seja extendida.

class Outer {

public void doSomething() {

Inner i = new Inner();

}

 

public final class Inner {

@Override

public String toString() {

return Outer.this + “/Inner”;

}

}

 

@Override

public String toString() {

return “Outer”;

}

}

 

class Another extends Outer.Inner { //ERRO: The type Another cannot subclass the final class Outer.Inner

public Another() {

new Outer().super();

}

 

@Override

public String toString() {

return “AnotherClass”;

}

}


Esta entrada foi publicada em inner class com as etiquetas . ligação permanente.

Uma resposta a O que significa uma regular inner-class com o modificador ‘final’ em sua declaração?

  1. Show! new Outer.super() eu nunca tinha visto! “Só sei q nada sei” já dizia o filósofo…

    Gostar

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s