0Pricing
Java Academy · Lección

Clases locales y anónimas

Declare clases dentro de métodos y cree implementaciones anónimas de interfaces sobre la marcha.

Clases locales y anónimas es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

Clases locales y anónimas

Las clases locales se definen dentro de un método. Las clases anónimas son clases locales sin nombre; combinan la declaración y la instanciación de la clase. Ambas capturan variables locales efectivamente finales.

Declaración de una clase local

Una clase local se declara dentro del cuerpo de un método. Puede acceder a los miembros de la clase contenedora y a las variables locales efectivamente finales.

static void greet(String language) {
    // Local class — defined inside the method
    class Greeter {
        String sayHello(String name) {
            // Can access 'language' — it is effectively final
            return switch (language) {
                case "EN" -> "Hello, " + name;
                case "ES" -> "Hola, " + name;
                case "FR" -> "Bonjour, " + name;
                default   -> "Hi, " + name;
            };
        }
    }

    Greeter g = new Greeter();
    System.out.println(g.sayHello("Alice"));
}
greet("ES"); // Hola, Alice

Variables efectivamente finales

Las clases locales y anónimas solo pueden capturar variables locales que sean efectivamente finales; es decir, que nunca se reasignen después de su inicialización.

void process(int threshold) {
    // threshold is effectively final (never reassigned)
    Runnable r = new Runnable() {
        public void run() {
            System.out.println("Threshold: " + threshold);
        }
    };
    r.run();

    // threshold = 10; // If you add this, the anonymous class won't compile
}

Conceptos básicos de las clases anónimas

Una clase anónima implementa una interfaz o extiende una clase directamente, dentro de una sola expresión.

interface Comparator<T> {
    int compare(T a, T b);
}

// Anonymous class implementing Comparator
java.util.Comparator<String> byLength = new java.util.Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return Integer.compare(a.length(), b.length());
    }
};

List<String> words = new ArrayList<>(List.of("banana", "fig", "apple", "kiwi"));
words.sort(byLength);
System.out.println(words); // [fig, kiwi, apple, banana]

Clase anónima frente a lambda

En las interfaces de un único método abstracto (SAM), las expresiones lambda sustituyen a las clases anónimas. Las clases anónimas siguen siendo necesarias para las interfaces con varios métodos o cuando se extienden clases abstractas.

// Anonymous class for single-method interface
Runnable r1 = new Runnable() {
    public void run() { System.out.println("Running!"); }
};

// Lambda — cleaner for SAM interfaces
Runnable r2 = () -> System.out.println("Running!");

// Must use anonymous class for multi-method interface:
java.io.FilenameFilter filter = new java.io.FilenameFilter() {
    public boolean accept(java.io.File dir, String name) {
        return name.endsWith(".java");
    }
}; // FilenameFilter is not a SAM — no lambda shorthand

Clase anónima con estado

Las clases anónimas pueden tener campos, a diferencia de las expresiones lambda. Esto resulta útil cuando necesita mantener un estado dentro de la implementación anónima.

interface Counter { int increment(); int get(); }

Counter counter = new Counter() {
    private int count = 0;

    public int increment() { return ++count; }
    public int get()       { return count; }
};

System.out.println(counter.increment()); // 1
System.out.println(counter.increment()); // 2
System.out.println(counter.get());       // 2

Patrón de listener anónimo

Antes de las expresiones lambda, las clases anónimas eran el patrón estándar para los listeners de eventos en la programación de interfaces gráficas y Android.

// Modern Android/Swing style: anonymous class listener
Button loginButton = new Button(); // hypothetical
loginButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick() {
        System.out.println("Login button clicked!");
    }
});

// Modern equivalent with lambda (if OnClickListener is SAM):
loginButton.setOnClickListener(() -> System.out.println("Clicked!"));

Clase local para lógica compleja

Las clases locales funcionan bien cuando necesita una clase con varios métodos en un único lugar: son demasiado complejas para una expresión lambda, pero demasiado específicas para una clase de nivel superior.

static List<String> processData(List<String> data, String prefix) {
    // Local class: complex enough for a class, used only here
    class DataProcessor {
        List<String> result = new ArrayList<>();

        void process(String item) {
            // prefix is effectively final
            if (item.startsWith(prefix)) {
                result.add(item.toUpperCase());
            }
        }
    }
    DataProcessor dp = new DataProcessor();
    data.forEach(dp::process);
    return dp.result;
}
System.out.println(processData(List.of("apple","avocado","banana"), "a"));
// [APPLE, AVOCADO]

Clase anónima para una clase abstracta

Las clases anónimas pueden extender clases abstractas y sobrescribir sus métodos abstractos sin crear una subclase con nombre.

abstract class ReportFormatter {
    abstract String formatHeader(String title);
    abstract String formatBody(List<String> rows);

    String format(String title, List<String> rows) {
        return formatHeader(title) + "\n" + formatBody(rows);
    }
}

ReportFormatter csvFormatter = new ReportFormatter() {
    public String formatHeader(String t) { return "\"" + t + "\""; }
    public String formatBody(List<String> rows) {
        return String.join("\n", rows);
    }
};
System.out.println(csvFormatter.format("Sales", List.of("a,1","b,2")));

Antipatrón de inicialización con doble llave

El truco de inicialización con doble llave utiliza clases anónimas para inicializar colecciones. Crea una subclase con un inicializador de instancia. Evítelo: es ineficiente y propenso a errores.

// Anti-pattern: double-brace initialization
Map<String, Integer> map = new HashMap<String, Integer>() {{
    put("a", 1);
    put("b", 2);
}};
// Creates an anonymous HashMap subclass — wasteful!

// GOOD: use Map.of() or Map.ofEntries()
Map<String, Integer> better = Map.of("a", 1, "b", 2);

// Or a mutable map:
Map<String, Integer> mutable = new HashMap<>(Map.of("a", 1, "b", 2));

Elección: lambda, anónima o local

Guía para decidir:

  • Lambda: un único método abstracto, sin estado adicional y sin herencia
  • Clase anónima: varios métodos, necesidad de mantener un estado o extensión de una clase abstracta
  • Clase local: necesidad de reutilización dentro del método, varios métodos o estado complejo

Comprobación rápida

¿Qué hace siempre una clase anónima dentro de una sola expresión?

Repaso: clases locales y anónimas

Ideas clave:

  • Las clases locales se definen dentro de métodos y pueden acceder a variables locales efectivamente finales
  • Las clases anónimas combinan la declaración y la instanciación de la clase en una sola expresión
  • Las clases anónimas pueden tener campos y varios métodos, a diferencia de las expresiones lambda
  • Las expresiones lambda sustituyen a las clases anónimas en las interfaces de un único método abstracto
  • Utilice clases locales cuando la lógica sea suficientemente compleja para una clase, pero específica de un solo método
  • Evite la inicialización con doble llave: crea subclases anónimas innecesarias

Preguntas frecuentes

¿La lección «Clases locales y anónimas» es gratis?

Sí — el texto completo de «Clases locales y anónimas» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Clases locales y anónimas»?

Declare clases dentro de métodos y cree implementaciones anónimas de interfaces sobre la marcha. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Clases locales y anónimas»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Clases anidadas estáticas
  2. Clases internas y acceso a la clase externa
  3. Clases locales y anónimas
  4. Elección de la estrategia de anidamiento adecuada
← Volver a Java Academy