1. Classe local
Uma classe local é uma classe declarada dentro de um método (ou até dentro de um bloco de código, por exemplo, em um loop ou em um bloco if). Ela é visível e acessível apenas dentro desse método e, fora dele, é como se não existisse. Ao contrário das classes anônimas, a classe local tem um nome (mesmo que simples), pode conter vários métodos e até campos.
Fazendo uma analogia — imagine que você prepara um prato complexo seguindo uma receita. Em um dos passos, você precisa preparar um molho especial, usado somente nessa receita e em mais nenhuma. Em vez de publicar um livro separado só para esse molho, você descreve o preparo diretamente dentro da receita principal. A classe local funciona exatamente assim — é uma “receita dentro da receita”, necessária apenas em um método específico.
Exemplo de declaração de classe local
public class Outer {
void someMethod() {
class Local {
void print() {
System.out.println("Hello from Local!");
}
}
Local local = new Local();
local.print();
}
}
Aqui a classe Local é declarada dentro do método someMethod da classe Outer. Ela existe apenas nesse método e não é visível de fora.
Sintaxe das classes locais
A declaração de uma classe local é parecida com a de uma classe comum, só que acontece dentro de um método:
void myMethod() {
class MyLocalClass {
void doSomething() {
System.out.println("A classe local está funcionando!");
}
}
MyLocalClass obj = new MyLocalClass();
obj.doSomething();
}
Particularidades da sintaxe:
- Uma classe local pode ser declarada dentro de qualquer método, construtor ou até bloco de inicialização.
- O nome da classe local é obrigatório (diferente das classes anônimas).
- Uma classe local não pode ser declarada com modificadores de acesso (public, private, protected) nem com o modificador static.
- Uma classe local pode implementar interfaces ou estender outras classes.
Comparação de tipos de classes:
public class Example {
// 1. Classe comum (em arquivo separado)
// class RegularClass { ... }
// 2. Classe interna (dentro de uma classe)
class InnerClass { }
// 3. Classe aninhada estática (dentro de uma classe)
static class NestedClass { }
void method() {
// 4. Classe local (no método)
class LocalClass { }
// 5. Classe anônima (no método, sem nome)
Object obj = new Object() { };
}
}
Classe local = uma classe nomeada apenas para este método!
2. Características das classes locais
Acesso às variáveis do método
Uma classe local pode acessar:
- Os campos da classe externa (mesmo que sejam private).
- Apenas as variáveis final ou efetivamente finais do método envolvente.
O que é “efetivamente final”?
É a variável cujo valor não muda após a inicialização. Por exemplo:
void foo() {
int x = 5; // efetivamente final
class L { void print() { System.out.println(x); } }
}
Se mais tarde você escrevesse x = 10;, o compilador reclamaria.
Por que isso?
Isso está relacionado a como o Java implementa classes locais “por baixo dos panos”: as variáveis do método são, na prática, copiadas para dentro da classe local, e não armazenadas por referência. Se a variável pudesse mudar, a classe local poderia trabalhar com uma cópia desatualizada — o que levaria a bugs e dor de cabeça.
Exemplo com acesso às variáveis
public class Outer {
private String secret = "segredo!";
void revealSecret() {
String greeting = "Olá,"; // efetivamente final
class Revealer {
void printSecret() {
System.out.println(greeting + " " + secret);
}
}
Revealer revealer = new Revealer();
revealer.printSecret();
}
}
3. Aplicações das classes locais: por que e quando?
Classes locais não são uma ferramenta para todos os dias, mas às vezes deixam o código mais limpo e compacto. Eis quando vale a pena usá-las:
- Lógica auxiliar específica de um único método.
Por exemplo, se for preciso implementar no método uma ordenação complexa, filtragem ou uma estrutura de dados temporária. - Encapsulamento para não “poluir” a classe com tipos desnecessários.
Se a classe é necessária só em um lugar, por que torná-la visível em toda a classe ou pacote? - Implementação de padrões de projeto em que objetos auxiliares são necessários apenas localmente.
Exemplo: ordenação com uma classe local
Suponha que você tenha uma lista de nomes e queira ordená-los pelo tamanho. Você pode criar uma classe local comparadora:
import java.util.*;
public class NameSorter {
public void sortNames(List<String> names) {
class LengthComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
return Integer.compare(a.length(), b.length());
}
}
Collections.sort(names, new LengthComparator());
}
}
Exemplo: estrutura temporária
Às vezes, é preciso criar uma estrutura auxiliar para processar dados em um único método:
void processScores(int[] scores) {
class ScoreInfo {
int score;
boolean passed;
ScoreInfo(int score) {
this.score = score;
this.passed = score >= 60;
}
}
for (int s : scores) {
ScoreInfo info = new ScoreInfo(s);
System.out.println("Nota: " + info.score + ", aprovado: " + info.passed);
}
}
4. Classes locais vs. classes anônimas
Às vezes surge a pergunta: para que servem classes locais se existem as anônimas? Vamos entender.
- Classe local — é uma classe nomeada, que pode ser usada várias vezes no método, à qual se pode adicionar campos, vários métodos e até classes internas.
- Classe anônima — é uma implementação pontual de uma interface ou classe, sem nome, geralmente com um único método (ou a sobrescrita de um ou dois métodos).
Quando usar:
- Se a lógica é simples e necessária apenas uma vez — use uma classe anônima.
- Se você precisa de mais métodos ou campos, ou se a classe será usada em vários pontos do método — use uma classe local.
Exemplo de comparação
Classe anônima:
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("Rápido e anônimo!");
}
};
Classe local:
void doWork() {
class MyWorker implements Runnable {
@Override
public void run() {
System.out.println("Eu sou uma classe local!");
}
}
MyWorker worker = new MyWorker();
worker.run();
}
5. Restrições e características das classes locais
- Modificadores de acesso: Uma classe local não pode ser declarada como public, private ou protected. Também não é possível adicionar static.
- Membros estáticos: Uma classe local não pode conter membros estáticos, exceto constantes (static final).
- Escopo de visibilidade: A classe local é visível apenas no bloco em que foi declarada.
- Uso de parâmetros genéricos: A classe local pode ser genérica, se necessário.
- Aninhamento: É possível declarar classes locais dentro de outras classes locais (mas não exagere, ou o código vai ficar parecendo uma matriosca).
6. Classes locais em um aplicativo real
Vamos continuar evoluindo nosso aplicativo de aprendizado. Suponha que exista uma classe Quiz, que faz perguntas ao usuário e verifica as respostas. Queremos criar, dentro do método de verificação, uma classe temporária que guarde a resposta do usuário e o status da verificação.
Exemplo: uso de uma classe local no aplicativo
import java.util.Scanner;
public class Quiz {
private String question = "Capital da França?";
private String correctAnswer = "Paris";
public void runQuiz() {
Scanner scanner = new Scanner(System.in);
System.out.println(question);
String userAnswer = scanner.nextLine();
// Classe local para armazenar o resultado
class AnswerResult {
String answer;
boolean isCorrect;
AnswerResult(String answer) {
this.answer = answer;
this.isCorrect = answer.equalsIgnoreCase(correctAnswer);
}
void printResult() {
if (isCorrect) {
System.out.println("Correto!");
} else {
System.out.println("Incorreto, a resposta correta é: " + correctAnswer);
}
}
}
AnswerResult result = new AnswerResult(userAnswer);
result.printResult();
}
}
Aqui a classe AnswerResult existe apenas dentro do método runQuiz e não é necessária em nenhum outro lugar. É um ótimo exemplo de classe local na prática!
7. Erros comuns ao trabalhar com classes locais
Erro nº 1: tentar acessar uma variável do método que não é final nem efetivamente final.
Se você declarou uma variável no método e, depois de usá-la na classe local, alterou seu valor, o compilador vai emitir um erro. Sempre garanta que tais variáveis não mudem após a inicialização.
Erro nº 2: querer adicionar modificadores de acesso ou static.
Uma classe local não pode ser declarada com os modificadores public, private, protected nem com static. Se você tentar — o compilador vai reclamar.
Erro nº 3: tentar usar a classe local fora do método.
A classe local vive apenas no método (ou bloco) em que é declarada. Ela não está acessível a partir de outros métodos nem fora da classe.
Erro nº 4: abusar de classes locais para lógica complexa.
Se sua classe local está ficando grande demais, com muitos métodos ou campos — provavelmente é melhor extraí-la para uma classe separada. Classes locais são boas para tarefas compactas e auxiliares.
GO TO FULL VERSION