Enums e Classes Internas

Esta lição cobre enums e classes internas—tipos especiais de classes em Java.

Enums

Enums são usados para definir um conjunto fixo de constantes.

Definindo um Enum

JAVA
public enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

Usando Enums

JAVA
public class EnumDemo {
    public static void main(String[] args) {
        Season season = Season.SPRING;
        
        switch (season) {
            case SPRING:
                System.out.println("Primavera");
                break;
            case SUMMER:
                System.out.println("Verão");
                break;
            case AUTUMN:
                System.out.println("Outono");
                break;
            case WINTER:
                System.out.println("Inverno");
                break;
        }
    }
}

Atributos e Métodos do Enum

JAVA
public enum Season {
    SPRING("Primavera", 1),
    SUMMER("Verão", 2),
    AUTUMN("Outono", 3),
    WINTER("Inverno", 4);
    
    private String name;
    private int order;
    
    // Construtor
    Season(String name, int order) {
        this.name = name;
        this.order = order;
    }
    
    // Getters
    public String getName() {
        return name;
    }
    
    public int getOrder() {
        return order;
    }
}

Métodos Comuns do Enum

Método Descrição Exemplo
values() Todos os valores do enum Season.values()
valueOf() String para enum Season.valueOf("SPRING")
ordinal() Índice do enum Season.SPRING.ordinal() → 0
name() Nome do enum Season.SPRING.name() → "SPRING"

Exemplo: Métodos do Enum

JAVA
public class EnumMethodDemo {
    public static void main(String[] args) {
        // Iterar todos os valores do enum
        for (Season s : Season.values()) {
            System.out.println(s.ordinal() + ": " + s.getName());
        }
        
        // String para enum
        Season spring = Season.valueOf("SPRING");
        System.out.println(spring.getName());  // Primavera
        
        // Comparar enums
        System.out.println(Season.SPRING == Season.SPRING);  // true
        System.out.println(Season.SPRING.equals(Season.SPRING));  // true
    }
}
▶ Experimente

Exemplo: Enum Weekday

JAVA
public enum Weekday {
    MONDAY("Segunda", true),
    TUESDAY("Terça", true),
    WEDNESDAY("Quarta", true),
    THURSDAY("Quinta", true),
    FRIDAY("Sexta", true),
    SATURDAY("Sábado", false),
    SUNDAY("Domingo", false);
    
    private String name;
    private boolean isWorkday;
    
    Weekday(String name, boolean isWorkday) {
        this.name = name;
        this.isWorkday = isWorkday;
    }
    
    public String getName() {
        return name;
    }
    
    public boolean isWorkday() {
        return isWorkday;
    }
}

public class WeekdayDemo {
    public static void main(String[] args) {
        for (Weekday day : Weekday.values()) {
            String type = day.isWorkday() ? "Dia útil" : "Fim de semana";
            System.out.println(day.getName() + " - " + type);
        }
    }
}
▶ Experimente

Classes Internas

Classes internas são definidas dentro de outra classe.

Classe Interna de Membro

JAVA
public class Outer {
    private int x = 10;
    
    // Classe interna de membro
    public class Inner {
        public void show() {
            // Pode acessar membros privados da classe externa
            System.out.println("x = " + x);
        }
    }
    
    public void test() {
        Inner inner = new Inner();
        inner.show();
    }
}

public class InnerClassDemo {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.show();  // x = 10
    }
}

Classe Interna Estática

JAVA
public class Outer {
    private static int x = 10;
    private int y = 20;
    
    // Classe interna estática
    public static class StaticInner {
        public void show() {
            // Só pode acessar membros estáticos da classe externa
            System.out.println("x = " + x);
            // System.out.println("y = " + y);  // Erro de compilação!
        }
    }
}

public class StaticInnerDemo {
    public static void main(String[] args) {
        // Não precisa criar objeto da classe externa
        Outer.StaticInner inner = new Outer.StaticInner();
        inner.show();  // x = 10
    }
}

Classe Interna Local

JAVA
public class Outer {
    public void method() {
        // Classe interna local: definida em um método
        class LocalInner {
            public void show() {
                System.out.println("Classe interna local");
            }
        }
        
        LocalInner inner = new LocalInner();
        inner.show();
    }
}

Classe Interna Anônima

JAVA
public interface Greeting {
    void greet(String name);
}

public class AnonymousDemo {
    public static void main(String[] args) {
        // Classe interna anônima
        Greeting hello = new Greeting() {
            @Override
            public void greet(String name) {
                System.out.println("Hello, " + name + "!");
            }
        };
        
        hello.greet("Alice");  // Hello, Alice!
        
        // Abreviação Lambda (interface funcional)
        Greeting hi = name -> System.out.println("Hi, " + name + "!");
        hi.greet("Bob");  // Hi, Bob!
    }
}

Exemplo: Classe Interna Anônima para Tratamento de Eventos

JAVA
public interface OnClickListener {
    void onClick(String button);
}

public class Button {
    private String text;
    private OnClickListener listener;
    
    public Button(String text) {
        this.text = text;
    }
    
    public void setOnClickListener(OnClickListener listener) {
        this.listener = listener;
    }
    
    public void click() {
        if (listener != null) {
            listener.onClick(text);
        }
    }
}

public class ButtonDemo {
    public static void main(String[] args) {
        Button btn = new Button("Enviar");
        
        // Classe interna anônima
        btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(String button) {
                System.out.println(button + " foi clicado");
            }
        });
        
        btn.click();  // Enviar foi clicado
    }
}
▶ Experimente

Comparação de Classes Internas

Tipo Localização Acesso à Classe Externa Criação
Classe interna de membro Dentro da classe Todos os membros outer.new Inner()
Classe interna estática Dentro da classe Membros estáticos new Outer.Inner()
Classe interna local Dentro do método Todos os membros + local final Criar dentro do método
Classe interna anônima Qualquer lugar Mesmo que local new Interface(){}

❓ Perguntas Frequentes

P: Quando devo usar enums? R: Ao definir um conjunto fixo de constantes, como estações, dias da semana ou estados.

P: Quando devo usar classes internas anônimas? R: Para implementações simples de interfaces, especialmente callbacks de eventos. Java 8+ recomenda Lambda para interfaces funcionais.

P: Para que servem as classes internas? R: Implementar callbacks, acessar membros privados da classe externa, organizar classes relacionadas.

📖 Resumo

📝 Exercícios

  1. Enum de estações: Defina um enum Season com nome da estação e intervalo de temperatura
  2. Máquina de estados: Implemente estados de pedido usando enums (Pendente, Pago, Enviado, Concluído)
  3. Classe interna anônima: Use classe interna anônima para implementar ordenação Comparator

Próxima Lição

Na próxima lição, aprenderemos sobre Tratamento de Exceções — como lidar com erros em programas.

100%