제네릭(Generics)은 클래스나 메서드에서 사용할 데이터 타입을 컴파일 시점에 지정하는 기능이다.
타입 안정성을 확보하고 불필요한 형변환을 제거하여 코드의 품질을 높인다.
제네릭 클래스 구현
타입 파라미터 T를 사용하여 다양한 타입을 수용할 수 있는 클래스를 정의한다.
public class Box<T> {
private T item;
public void set(T item) { this.item = item; }
public T get() { return item; }
}
// 사용 예시
Box<String> nameBox = new Box<>();
nameBox.set("Java");
String name = nameBox.get(); // 형변환 불필요
제네릭 메서드
클래스 전체가 아닌 특정 메서드에만 제네릭을 적용할 수 있다.
public class Util {
// <T>는 리턴 타입 앞에 선언
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
}
// 사용 예시
Integer[] nums = {1, 2, 3};
Util.printArray(nums);
제한된 타입 파라미터 (Bounded Type Parameters)
extends 키워드를 사용하여 특정 클래스의 자식 클래스만 타입으로 지정할 수 있도록 제한한다.
// Number 클래스나 그 자식 클래스(Integer, Double 등)만 허용
public class Calculator<T extends Number> {
public double add(T n1, T n2) {
return n1.doubleValue() + n2.doubleValue();
}
}
주요 이점
- 타입 안정성: 잘못된 타입의 객체가 저장되는 것을 컴파일 단계에서 차단한다.
- 형변환 생략: 데이터를 꺼낼 때마다
(String)과 같이 강제 형변환을 할 필요가 없어 코드가 간결해진다. - 재사용성: 하나의 클래스/메서드로 다양한 데이터 타입을 처리할 수 있어 중복 코드가 줄어든다.
P.S
제네릭은 자바 컬렉션 프레임워크의 핵심 기술이며, 타입 관련 런타임 오류를 컴파일 타임 오류로 전환하여 프로그램의 견고함을 높인다.
와일드카드(?)와 같은 고급 개념을 함께 익히면 더 유연한 설계가 가능하는 것 같다.