0

[Java Backend Zero to Hello] BÀI 2.10: ENUM & NESTED CLASS

Java Backend Zero to Hello

📚 Bài viết thuộc series Java Backend Zero to Hello 📌 Phần: Phase 2: Java Core Nâng Cao | Bài 25/86


BÀI 2.10: ENUM & NESTED CLASS

Mục tiêu

  • Sử dụng Enum nâng cao
  • Phân biệt các loại Nested Class
  • Áp dụng Inner Class, Anonymous Class
  • Hiểu về Local Class

1. ENUM CƠ BẢN

Enum là kiểu dữ liệu đặc biệt để định nghĩa tập hợp hằng số cố định.

public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

Day today = Day.MONDAY;

2. ENUM NÂNG CAO

2.1 Enum với thuộc tính và method

public enum OrderStatus {
    PENDING("Đang chờ"),
    CONFIRMED("Đã xác nhận"),
    SHIPPING("Đang giao"),
    DELIVERED("Đã giao"),
    CANCELLED("Đã hủy");

    private final String displayName;

    OrderStatus(String displayName) {
        this.displayName = displayName;
    }

    public String getDisplayName() {
        return displayName;
    }
}

2.2 Enum với method trừu tượng

public enum Operation {
    PLUS {
        @Override
        public double apply(double x, double y) {
            return x + y;
        }
    },
    MINUS {
        @Override
        public double apply(double x, double y) {
            return x - y;
        }
    },
    MULTIPLY {
        @Override
        public double apply(double x, double y) {
            return x * y;
        }
    },
    DIVIDE {
        @Override
        public double apply(double x, double y) {
            return x / y;
        }
    };

    public abstract double apply(double x, double y);
}

double result = Operation.PLUS.apply(5, 3);  // 8

2.3 Các method hữu ích

// values() - tất cả giá trị
OrderStatus[] all = OrderStatus.values();

// valueOf() - tìm theo tên
OrderStatus status = OrderStatus.valueOf("PENDING");

// name() - tên
String name = OrderStatus.PENDING.name();  // "PENDING"

// ordinal() - vị trí
int ordinal = OrderStatus.PENDING.ordinal();  // 0

2.4 EnumSet và EnumMap

// EnumSet - Set hiệu quả cho enum
EnumSet<OrderStatus> activeStatuses = EnumSet.of(
    OrderStatus.PENDING, OrderStatus.CONFIRMED
);

// EnumMap - Map hiệu quả cho enum key
EnumMap<OrderStatus, String> statusMessages = new EnumMap<>(OrderStatus.class);
statusMessages.put(OrderStatus.PENDING, "Đang xử lý");

3. NESTED CLASS

Class được khai báo bên trong class khác.

3.1 Static Nested Class

public class Outer {
    private static int outerStatic = 10;
    private int outerInstance = 20;

    public static class StaticNested {
        public void display() {
            System.out.println("Outer static: " + outerStatic);
            // System.out.println(outerInstance);  // ❌ Không truy cập được
        }
    }
}

// Sử dụng
Outer.StaticNested nested = new Outer.StaticNested();
nested.display();

3.2 Inner Class (Non-static Nested)

public class Outer {
    private int outerInstance = 20;

    public class Inner {
        public void display() {
            System.out.println("Outer instance: " + outerInstance);  // ✅ Truy cập được
        }
    }
}

// Sử dụng - cần instance của Outer
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display();

3.3 Local Class

Class khai báo trong method.

public void process() {
    final int localVar = 10;

    class LocalClass {
        public void display() {
            System.out.println("Local var: " + localVar);
        }
    }

    LocalClass obj = new LocalClass();
    obj.display();
}

3.4 Anonymous Class

Class không tên, dùng để implement interface hoặc extend class ngay tại chỗ.

// Implement interface
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("Anonymous runnable");
    }
};

// Extend class
Animal animal = new Animal() {
    @Override
    public void makeSound() {
        System.out.println("Anonymous sound");
    }
};

💡 Trong Java 8+, thường dùng Lambda thay Anonymous Class cho Functional Interface.


4. SO SÁNH CÁC LOẠI NESTED CLASS

Loại Truy cập Outer Khai báo Khi nào dùng
Static Nested Chỉ static Trong class Helper class, không cần outer instance
Inner Cả static và instance Trong class Cần truy cập instance của outer
Local Cả hai Trong method Chỉ dùng trong method
Anonymous Cả hai Tại chỗ Implement nhanh (nên thay bằng Lambda)

5. VÍ DỤ THỰC TẾ

5.1 Builder Pattern với Static Nested

public class User {
    private final String name;
    private final String email;
    private final int age;

    private User(Builder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
    }

    public static class Builder {
        private String name;
        private String email;
        private int age;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder email(String email) {
            this.email = email;
            return this;
        }

        public Builder age(int age) {
            this.age = age;
            return this;
        }

        public User build() {
            return new User(this);
        }
    }
}

// Sử dụng
User user = new User.Builder()
    .name("An")
    .email("an@example.com")
    .age(25)
    .build();

5.2 LinkedList với Inner Class

public class LinkedList<T> {
    private Node head;
    private int size;

    private class Node {
        T data;
        Node next;

        Node(T data) {
            this.data = data;
        }
    }

    public void add(T data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
        } else {
            Node current = head;
            while (current.next != null) {
                current = current.next;
            }
            current.next = newNode;
        }
        size++;
    }
}

6. BÀI TẬP THỰC HÀNH

Bài 1: Enum với logic

public enum PaymentMethod {
    CASH {
        @Override
        public double calculateFee(double amount) {
            return 0;
        }
    },
    CREDIT_CARD {
        @Override
        public double calculateFee(double amount) {
            return amount * 0.02;
        }
    },
    BANK_TRANSFER {
        @Override
        public double calculateFee(double amount) {
            return 5000;
        }
    };

    public abstract double calculateFee(double amount);
}

Bài 2: Enum với thuộc tính

public enum HttpStatus {
    OK(200, "Thành công"),
    BAD_REQUEST(400, "Yêu cầu không hợp lệ"),
    NOT_FOUND(404, "Không tìm thấy"),
    INTERNAL_SERVER_ERROR(500, "Lỗi server");

    private final int code;
    private final String message;

    HttpStatus(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode() { return code; }
    public String getMessage() { return message; }

    public static HttpStatus fromCode(int code) {
        for (HttpStatus status : values()) {
            if (status.code == code) return status;
        }
        throw new IllegalArgumentException("Unknown code: " + code);
    }
}

Bài 3: Static Nested cho Repository

public class UserRepository {
    private final Map<Long, User> users = new HashMap<>();

    public void save(User user) {
        users.put(user.getId(), user);
    }

    public Optional<User> findById(Long id) {
        return Optional.ofNullable(users.get(id));
    }

    // Static nested class cho query builder
    public static class QueryBuilder {
        private String namePattern;
        private Integer minAge;

        public QueryBuilder nameLike(String pattern) {
            this.namePattern = pattern;
            return this;
        }

        public QueryBuilder minAge(int age) {
            this.minAge = age;
            return this;
        }

        public List<User> execute() {
            // Logic query
            return new ArrayList<>();
        }
    }
}

7. TÓM TẮT

Khái niệm Mô tả
Enum Tập hợp hằng số có kiểu
Enum method Có thể có method, field
Enum abstract Mỗi giá trị override method
Static Nested Class tĩnh trong class
Inner Class Class không tĩnh, cần outer instance
Local Class Class trong method
Anonymous Class Class không tên

Bài tiếp theo: 2.11 Java 9-17 features


🧭 Điều Hướng Series

⬅️ Bài trước: BÀI 2.9: ANNOTATION & REFLECTION

📋 Lộ trình tổng quan: Xem Toàn Bộ Series

➡️ Bài tiếp theo: BÀI 2.11: JAVA 9-17 FEATURES


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí