1. Classe aninhada estática
Classe aninhada estática (static nested class) — é uma classe declarada dentro de outra classe com o modificador static. Na essência, é uma classe comum que apenas “vive” dentro de outra classe, mas não está vinculada ao objeto dela.
Se a classe interna é como um irmão mais novo que sempre dá a mão ao mais velho (o objeto da classe externa), então a aninhada estática é como um primo que aparece só nas festas de família e, no resto do tempo, vive a própria vida.
Principais diferenças:
- Não possui referência implícita ao objeto da classe externa — nada de OuterClass.this e sem acesso a membros não estáticos.
- Pode conter membros estáticos (ao contrário da classe interna comum).
- É criada sem um objeto da classe externa.
Sintaxe de declaração
Declarar uma classe aninhada estática é muito simples: usamos a palavra‑chave static dentro da classe externa.
class Outer {
static class Nested {
void print() {
System.out.println("Hello from Nested!");
}
}
}
E só! Nada de construções sintáticas mirabolantes — apenas static class.
Visualização:
Outer (classe externa)
│
├── Nested (classe aninhada estática)
│ └── print()
2. Criação de instância da classe aninhada estática
O mais legal: não é necessário um objeto da classe externa!
Outer.Nested nested = new Outer.Nested();
nested.print(); // Hello from Nested!
Observe que usamos o nome completo da classe — Outer.Nested. É como se referir à classe aninhada pelo sobrenome: “Smith.Son”.
Compare com a classe interna (inner):
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // precisa do objeto outer
Já para a static nested — o objeto Outer não é necessário!
3. Acesso aos membros da classe externa
É aqui que está a principal diferença em relação à classe interna.
- A classe aninhada estática tem acesso SOMENTE aos membros estáticos da classe externa.
- Não é possível acessar campos e métodos não estáticos (mesmo que sejam public).
Exemplo:
class Outer {
private static int staticValue = 10;
private int instanceValue = 20;
static class Nested {
void show() {
System.out.println("Static value: " + staticValue); // OK
// System.out.println("Instance value: " + instanceValue); // Erro!
}
}
}
Se você tentar acessar o campo não estático instanceValue, o compilador reclamará imediatamente.
Por que isso? Porque a static nested class não “sabe” a qual objeto Outer deve ser associada — ela não tem referência ao objeto da classe externa.
4. Quando usar classes aninhadas estáticas
Quando são apropriadas?
- Quando a classe aninhada está logicamente relacionada à externa, mas não precisa de acesso ao objeto da classe externa.
- Quando você quer encapsular uma estrutura auxiliar: por exemplo, um builder, utilitário, enumeração ou até um pequeno objeto imutável.
- Quando é preciso reduzir a “poluição” do pacote: a classe é necessária apenas para a classe externa, não faz sentido levá-la para fora.
Cenários típicos:
- Padrão Builder (especialmente para objetos imutáveis)
- Implementação de estruturas auxiliares: por exemplo, classes Node internas em coleções
- Agrupamento de constantes ou utilitários
Regra simples de escolha
Faça a si mesmo a pergunta: “A minha classe aninhada precisa de acesso a um objeto específico da classe externa?”
NÃO → use static class (classe aninhada estática)
SIM → use uma class comum (interna)
5. Exemplos de uso
Exemplo 1: Builder para uma classe
Suponha que temos a classe Person e queremos implementar o padrão Builder para ela:
public class Person {
private final String name;
private final int age;
// Construtor privado
private Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}
// Classe aninhada estática Builder
public static class Builder {
private String name;
private int age;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(this);
}
}
public void printInfo() {
System.out.println("Person: " + name + ", " + age);
}
}
Uso:
Person person = new Person.Builder()
.setName("Ivan")
.setAge(30)
.build();
person.printInfo(); // Person: Ivan, 30
Por que o Builder é uma classe aninhada estática?
Porque ele não depende de um objeto Person, apenas ajuda a criá-lo. Ele está logicamente ligado a Person, mas não a uma instância específica.
Exemplo 2: Estrutura auxiliar dentro de uma coleção
Imagine uma classe “caixa de inteiros”, em que para armazenar os elementos é usada uma classe estática interna Node:
public class IntBox {
private Node head;
// Classe estática aninhada
private static class Node {
int value;
Node next;
Node(int value) {
this.value = value;
}
}
public void add(int value) {
Node node = new Node(value);
node.next = head;
head = node;
}
public void printAll() {
Node current = head;
while (current != null) {
System.out.println(current.value);
current = current.next;
}
}
}
Uso:
IntBox box = new IntBox();
box.add(1);
box.add(2);
box.add(3);
box.printAll(); // 3 2 1
Por que Node é static?
Porque cada Node não precisa conhecer toda a caixa (IntBox); ele apenas armazena os dados e a referência para o próximo Node.
Exemplo 3: Classe utilitária dentro da principal
public class MathUtils {
// Classe aninhada estática para trabalhar com números complexos
public static class Complex {
private final double re;
private final double im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
public Complex add(Complex other) {
return new Complex(this.re + other.re, this.im + other.im);
}
@Override
public String toString() {
return re + " + " + im + "i";
}
}
}
Uso:
MathUtils.Complex a = new MathUtils.Complex(1, 2);
MathUtils.Complex b = new MathUtils.Complex(3, 4);
MathUtils.Complex sum = a.add(b);
System.out.println(sum); // 4.0 + 6.0i
6. Nuances úteis
Classe interna vs classe aninhada estática
| Classe interna (inner) | Classe aninhada estática (static nested) | |
|---|---|---|
| Palavra‑chave | nenhuma | |
| Referência implícita ao objeto externo | sim | não |
| Acesso aos membros não estáticos da classe externa | sim | não |
| Acesso aos membros estáticos da classe externa | sim | sim |
| Pode conter membros estáticos | não (apenas constantes) | sim |
| Sintaxe de criação | |
|
| Uso | Quando é necessário acessar o objeto da classe externa | Quando não é necessário acessar o objeto da classe externa |
Ilustração
flowchart LR
OuterClass -->|has| InnerClass
OuterClass -.->|has| StaticNestedClass
StaticNestedClass -.->|can access| staticMembers
InnerClass -->|can access| instanceMembers
InnerClass -->|can access| staticMembers
Características e limitações
- Static nested class pode conter tanto campos e métodos comuns quanto estáticos.
- Pode ser declarada com qualquer modificador de acesso (public, private, protected, package‑private).
- Pode implementar interfaces e herdar de outras classes.
- Pode ser generic.
- Normalmente é usada para encapsular classes de suporte que não são necessárias fora da classe externa.
Exemplo de classe aninhada estática genérica:
public class Box {
public static class Holder<T> {
private T value;
public Holder(T value) { this.value = value; }
public T get() { return value; }
}
}
Quando NÃO usar classe aninhada estática
- Se a classe aninhada precisar de acesso a campos/métodos não estáticos da classe externa — use uma inner class comum.
- Se a classe for necessária fora da classe externa — extraia para um arquivo separado.
- Se a classe for grande ou complexa demais — melhor torná-la separada.
7. Erros comuns e nuances
Erro nº 1: Confusão entre inner e classe aninhada estática.
Muitos iniciantes tentam acessar, a partir de uma classe aninhada estática, campos não estáticos da classe externa. Mas a static nested class não possui referência ao objeto da classe externa, portanto isso é impossível. Se você precisa acessar o estado de um objeto específico — use uma inner class comum.
Erro nº 2: Tentar criar uma classe aninhada estática por meio de um objeto da classe externa.
Não há necessidade de escrever outer.new Inner(). Para uma static nested class, sempre use new Outer.Nested().
Erro nº 3: Usar uma classe aninhada estática para lógica que exige acesso à instância da classe externa.
Se a lógica da classe está fortemente ligada ao estado do objeto externo, a static nested class é uma má escolha. Use uma classe interna comum.
Erro nº 4: Aninhamento excessivamente complexo.
Não exagere no uso de classes aninhadas. Se a estrutura começar a ficar confusa, é melhor extrair parte das classes para fora.
GO TO FULL VERSION