SeouliteLab

[Java/자바] Generics(제네릭) 이해하기 본문

프로그래밍

[Java/자바] Generics(제네릭) 이해하기

Seoulite Lab 2024. 3. 20. 08:42

Java에서 Generics(제네릭)은 타입을 파라미터로 가지는 클래스와 인터페이스를 만들 수 있게 해줍니다. 이를 통해 타입 안정성(type safety)을 제공하고, 코드의 가독성을 높이며, 잘못된 타입으로 인한 오류를 컴파일 시점에 잡을 수 있습니다.

예제 1: 제네릭 클래스 정의

class Box<T> {
    private T value;

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

    public T getValue() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        Box<Integer> integerBox = new Box<>();
        integerBox.setValue(10);
        System.out.println("Integer Value: " + integerBox.getValue());

        Box<String> stringBox = new Box<>();
        stringBox.setValue("Hello, Generics!");
        System.out.println("String Value: " + stringBox.getValue());
    }
}

예제 2: 제네릭 메서드

class Util {
    public static <T> T getLastElement(T[] array) {
        if (array == null || array.length == 0) {
            return null;
        }
        return array[array.length - 1];
    }
}

public class Main {
    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4, 5};
        Integer lastInt = Util.getLastElement(intArray);
        System.out.println("Last Integer: " + lastInt);

        String[] strArray = {"apple", "banana", "cherry"};
        String lastStr = Util.getLastElement(strArray);
        System.out.println("Last String: " + lastStr);
    }
}

예제 3: 제네릭 인터페이스

interface List<E> {
    void add(E element);
    E get(int index);
}

class ArrayList<E> implements List<E> {
    private Object[] elements;
    private int size;
    
    public ArrayList() {
        elements = new Object[10];
        size = 0;
    }

    @Override
    public void add(E element) {
        elements[size++] = element;
    }

    @Override
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        return (E) elements[index];
    }
}

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Generics");
        System.out.println("First Element: " + list.get(0));
    }
}

예제 4: 제네릭 제약(한정자)

class Box<T extends Number> {
    private T value;

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

    public T getValue() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        Box<Integer> intBox = new Box<>();
        intBox.setValue(10);
        System.out.println("Integer Value: " + intBox.getValue());

        // 컴파일 에러: String은 Number를 상속받지 않음
        // Box<String> strBox = new Box<>(); 
    }
}

예제 5: 제네릭 와일드카드

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static double sum(List<? extends Number> list)
	double sum = 0;
    for (Number num : list) {
        sum += num.doubleValue();
    }
    return sum;
}

public static void main(String[] args) {
    List<Integer> intList = new ArrayList<>();
    intList.add(1);
    intList.add(2);
    intList.add(3);

    System.out.println("Sum of Integers: " + sum(intList));

    List<Double> doubleList = new ArrayList<>();
    doubleList.add(1.5);
    doubleList.add(2.5);
    doubleList.add(3.5);

    System.out.println("Sum of Doubles: " + sum(doubleList));
}

예제 6: 제네릭 메서드와 와일드카드 조합

class Util {
    public static <T extends Comparable<T>> T getMax(T[] array) {
        if (array == null || array.length == 0) {
            return null;
        }
        T max = array[0];
        for (T element : array) {
            if (element.compareTo(max) > 0) {
                max = element;
            }
        }
        return max;
    }
}

public class Main {
    public static void main(String[] args) {
        Integer[] intArray = {10, 20, 30, 40, 50};
        System.out.println("Max Integer: " + Util.getMax(intArray));

        Double[] doubleArray = {3.5, 2.7, 5.9, 1.2};
        System.out.println("Max Double: " + Util.getMax(doubleArray));
    }
}