A classe interna Java é definida dentro do corpo de outra classe. A classe interna Java pode ser declarada como privada, pública, protegida ou com acesso padrão, enquanto uma classe externa só pode ter acesso público ou padrão. As classes aninhadas Java são divididas em dois tipos.
-
classe aninhada estática
Se a classe aninhada for estática, ela é chamada de classe aninhada estática. As classes aninhadas estáticas só podem acessar membros estáticos da classe externa. Uma classe aninhada estática é igual a qualquer outra classe de nível superior e é aninhada apenas por conveniência de empacotamento. Um objeto de classe estática pode ser criado com a seguinte instrução.
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
-
classe interna java
Qualquer classe aninhada não estática é conhecida como classe interna em java. A classe interna java está associada ao objeto da classe e pode acessar todas as variáveis e métodos da classe externa. Como as classes internas estão associadas à instância, não podemos ter variáveis estáticas nelas. O objeto da classe interna java faz parte do objeto da classe externa e para criar uma instância da classe interna, primeiro precisamos criar uma instância da classe externa. A classe interna java pode ser instanciada assim;
OuterClass outerObject = new OuterClass(); OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Há dois tipos especiais de classes internas Java.
-
classe interna local
Se uma classe for definida no corpo de um método, ela é conhecida como classe interna local. Como a classe interna local não está associada a um objeto, não podemos usar modificadores de acesso privado, público ou protegido com ela. Os únicos modificadores permitidos são abstrato ou final. Uma classe interna local pode acessar todos os membros da classe envolvente e as variáveis locais finais no escopo em que é definida. Além disso, também pode acessar uma variável local não final do método em que é definida, mas não pode modificá-las. Portanto, se você tentar imprimir o valor da variável local não final, será permitido, mas se tentar alterar seu valor de dentro da classe interna local do método, ocorrerá um erro de compilação. Uma classe interna local pode ser definida assim:
package com.journaldev.innerclasses; public class MainClass { private String s_main_class; public void print() { String s_print_method = ""; // classe interna local dentro do método class Logger { // capaz de acessar variáveis da classe envolvente String name = s_main_class; // capaz de acessar variáveis do método não finais String name1 = s_print_method; public void foo() { String name1 = s_print_method; // O código abaixo lançará um erro de compilação: // Variável local s_print_method definida em um escopo envolvente deve ser final ou efetivamente final // s_print_method= ":"; } } // instanciar classe interna local no método para uso Logger logger = new Logger(); } }
Podemos definir uma classe interna local dentro de qualquer bloco também, como bloco estático, bloco if-else, etc. No entanto, nesse caso, o escopo da classe será muito limitado.
public class MainClass { static { class Foo { } Foo f = new Foo(); } public void bar() { if(1 < 2) { class Test { } Test t1 = new Test(); } // Abaixo lançará um erro devido ao escopo da classe //Test t = new Test(); //Foo f = new Foo(); } }
-
classe interna anônima
Uma classe interna local sem nome é conhecida como classe interna anônima. Uma classe anônima é definida e instanciada em uma única instrução. Classes internas anônimas sempre estendem uma classe ou implementam uma interface. Como uma classe anônima não tem nome, não é possível definir um construtor para uma classe anônima. Classes internas anônimas são acessíveis apenas no ponto em que são definidas. É um pouco difícil definir como criar uma classe interna anônima, veremos o uso em tempo real no programa de teste abaixo.
Aqui está uma classe Java mostrando como definir uma classe interna Java, uma classe interna estática, uma classe interna local e uma classe interna anônima. OuterClass.java
package com.journaldev.nested;
import java.io.File;
import java.io.FilenameFilter;
public class OuterClass {
private static String name = "OuterClass";
private int i;
protected int j;
int k;
public int l;
//Construtor OuterClass
public OuterClass(int i, int j, int k, int l) {
this.i = i;
this.j = j;
this.k = k;
this.l = l;
}
public int getI() {
return this.i;
}
//Classe aninhada estática, pode acessar variáveis/métodos estáticos de OuterClass
static class StaticNestedClass {
private int a;
protected int b;
int c;
public int d;
public int getA() {
return this.a;
}
public String getName() {
return name;
}
}
//Classe interna, não estática e pode acessar todas as variáveis/métodos da classe externa
class InnerClass {
private int w;
protected int x;
int y;
public int z;
public int getW() {
return this.w;
}
public void setValues() {
this.w = i;
this.x = j;
this.y = k;
this.z = l;
}
@Override
public String toString() {
return "w=" + w + ":x=" + x + ":y=" + y + ":z=" + z;
}
public String getName() {
return name;
}
}
//Classe interna local
public void print(String initial) {
//Classe interna local inside the method
class Logger {
String name;
public Logger(String name) {
this.name = name;
}
public void log(String str) {
System.out.println(this.name + ": " + str);
}
}
Logger logger = new Logger(initial);
logger.log(name);
logger.log("" + this.i);
logger.log("" + this.j);
logger.log("" + this.k);
logger.log("" + this.l);
}
//Classe interna anônima
public String[] getFilesInDir(String dir, final String ext) {
File file = new File(dir);
//Classe interna anônima implementing FilenameFilter interface
String[] filesList = file.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(ext);
}
});
return filesList;
}
}
Aqui está o programa de teste mostrando como instanciar e usar a classe interna em Java. InnerClassTest.java
package com.journaldev.nested;
import java.util.Arrays;
//Classes aninhadas podem ser usadas em import para facilitar a instância
import com.journaldev.nested.OuterClass.InnerClass;
import com.journaldev.nested.OuterClass.StaticNestedClass;
public class InnerClassTest {
public static void main(String[] args) {
OuterClass outer = new OuterClass(1,2,3,4);
//Exemplo de classes aninhadas estáticas
StaticNestedClass staticNestedClass = new StaticNestedClass();
StaticNestedClass staticNestedClass1 = new StaticNestedClass();
System.out.println(staticNestedClass.getName());
staticNestedClass.d=10;
System.out.println(staticNestedClass.d);
System.out.println(staticNestedClass1.d);
//Exemplo de classe interna
InnerClass innerClass = outer.new InnerClass();
System.out.println(innerClass.getName());
System.out.println(innerClass);
innerClass.setValues();
System.out.println(innerClass);
//Chamando o método usando classe interna local
outer.print("Outer");
//Chamando o método usando classe interna anônima
System.out.println(Arrays.toString(outer.getFilesInDir("src/com/journaldev/nested", ".java")));
System.out.println(Arrays.toString(outer.getFilesInDir("bin/com/journaldev/nested", ".class")));
}
}
Aqui está a saída do programa de exemplo de classe interna Java acima.
OuterClass
10
0
OuterClass
w=0:x=0:y=0:z=0
w=1:x=2:y=3:z=4
Outer: OuterClass
Outer: 1
Outer: 2
Outer: 3
Outer: 4
[NestedClassTest.java, OuterClass.java]
[NestedClassTest.class, OuterClass$1.class, OuterClass$1Logger.class, OuterClass$InnerClass.class, OuterClass$StaticNestedClass.class, OuterClass.class]
Observe que, ao compilar OuterClass, arquivos de classe separados são criados para a classe interna, classe interna local e classe aninhada estática.
Benefícios da Classe Interna Java
- Se uma classe é útil apenas para uma classe, faz sentido mantê-la aninhada e junto. Isso ajuda na organização das classes.
- As classes internas do Java implementam encapsulamento. Note que as classes internas podem acessar membros privados da classe externa e ao mesmo tempo podemos ocultar a classe interna do mundo exterior.
- Mantendo a classe pequena dentro das classes de nível superior coloca o código mais próximo de onde é usado e torna o código mais legível e mantível.
Isso é tudo para classes internas do Java.
Source:
https://www.digitalocean.com/community/tutorials/java-inner-class