Java Generics: Type Safety ที่ยืดหยุ่น

#java13 เม.ย. 2569

Generics คืออะไร

Generics (Java 5+) ช่วยให้เขียน code ที่ type-safe และ reusable โดยไม่ต้อง cast หรือเสี่ยง ClassCastException

Generic Class

public class Box<T> {
    private T value;

    public Box(T value) { this.value = value; }
    public T getValue() { return value; }
    public void setValue(T value) { this.value = value; }

    @Override
    public String toString() {
        return "Box[" + value + "]";
    }
}

// ใช้งาน
Box<String> stringBox = new Box<>("Hello");
Box<Integer> intBox = new Box<>(42);

String s = stringBox.getValue();  // ไม่ต้อง cast
Integer i = intBox.getValue();

Generic Method

public class Utils {
    // Generic method
    public static <T> List<T> repeat(T item, int times) {
        List<T> result = new ArrayList<>();
        for (int i = 0; i < times; i++) {
            result.add(item);
        }
        return result;
    }

    // Multiple type parameters
    public static <K, V> Map<V, K> invertMap(Map<K, V> map) {
        Map<V, K> result = new HashMap<>();
        map.forEach((k, v) -> result.put(v, k));
        return result;
    }
}

// ใช้งาน
List<String> strings = Utils.repeat("hello", 3);
List<Integer> ints = Utils.repeat(42, 5);

Bounded Type Parameters

// Upper bound - T ต้องเป็น Number หรือ subclass
public static <T extends Number> double sum(List<T> list) {
    return list.stream()
        .mapToDouble(Number::doubleValue)
        .sum();
}

// Multiple bounds
public static <T extends Comparable<T> & Cloneable> T max(T a, T b) {
    return a.compareTo(b) >= 0 ? a : b;
}

// ใช้งาน
List<Integer> ints = List.of(1, 2, 3, 4, 5);
double total = sum(ints);  // 15.0

Wildcards

// ? extends T - upper bounded wildcard (read-only)
public double sumList(List<? extends Number> list) {
    return list.stream().mapToDouble(Number::doubleValue).sum();
}

// ? super T - lower bounded wildcard (write)
public void addNumbers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
    list.add(3);
}

// ? - unbounded wildcard
public void printList(List<?> list) {
    list.forEach(System.out::println);
}

Generic Interface

public interface Repository<T, ID> {
    Optional<T> findById(ID id);
    List<T> findAll();
    T save(T entity);
    void delete(ID id);
}

public class UserRepository implements Repository<User, Integer> {
    @Override
    public Optional<User> findById(Integer id) { ... }
    // implement other methods
}

สรุป

Generics ทำให้โค้ด type-safe และ reusable ลด boilerplate code และป้องกัน ClassCastException ที่ runtime ควรใช้ generics เมื่อต้องการ class หรือ method ที่ทำงานกับหลาย type ครับ