728x90

제네릭(Generic) 클래스란?
제네릭(Generic) 클래스는 타입을 파라미터로 받을 수 있는 클래스입니다. 즉, 클래스 내부에서 사용할 데이터 타입을 컴파일 타임에 지정할 수 있도록 하는 기능을 제공합니다. 이를 통해 코드의 재사용성을 높이고, 타입 안정성을 보장할 수 있습니다.
1. 제네릭 클래스 기본 구조
제네릭 클래스를 선언할 때는 클래스 이름 뒤에 <T>와 같은 타입 파라미터를 지정합니다.
// T는 타입 파라미터 (임의의 타입을 의미)
public class Box<T> {
private T item; // T 타입의 변수
// 생성자
public Box(T item) {
this.item = item;
}
// 값을 가져오는 메서드
public T getItem() {
return item;
}
// 값을 설정하는 메서드
public void setItem(T item) {
this.item = item;
}
}
2. 제네릭 클래스 사용 예시
제네릭 클래스를 사용할 때는 원하는 타입을 지정해야 합니다.
public class Main {
public static void main(String[] args) {
// String 타입을 지정한 Box 객체 생성
Box<String> stringBox = new Box<>("Hello");
System.out.println(stringBox.getItem()); // 출력: Hello
// Integer 타입을 지정한 Box 객체 생성
Box<Integer> intBox = new Box<>(100);
System.out.println(intBox.getItem()); // 출력: 100
}
}
- Box<String>을 사용하면 Box 클래스의 T가 String으로 대체됩니다.
- Box<Integer>를 사용하면 T가 Integer로 대체됩니다.
3. 제네릭의 장점
- 타입 안정성(Type Safety) 보장
- 컴파일 타임에 타입 검사가 이루어져 런타임 오류를 줄일 수 있음
- 잘못된 타입이 들어가는 것을 방지
- 형변환(Casting) 불필요
- 일반적인 Object 타입을 사용하면 값을 가져올 때 형변환이 필요하지만, 제네릭을 사용하면 불필요
// 제네릭을 사용하지 않는 경우 (Object 타입) Object obj = "Hello"; String str = (String) obj; // 형변환 필요 // 제네릭을 사용하는 경우 Box<String> box = new Box<>("Hello"); String str2 = box.getItem(); // 형변환 없이 바로 사용 가능 - 코드 재사용성 증가
- 여러 타입에 대해 동일한 코드로 동작할 수 있으므로 중복 코드 감소
- 유지보수성 향상
4. 제네릭 타입 제한 (Bounded Type Parameter)
extends 키워드를 사용하여 특정 클래스 또는 인터페이스를 상속한 타입만 사용할 수 있도록 제한할 수 있습니다.
// Number 또는 Number를 상속한 클래스만 사용 가능
public class NumberBox<T extends Number> {
private T number;
public NumberBox(T number) {
this.number = number;
}
public T getNumber() {
return number;
}
}
public class Main {
public static void main(String[] args) {
NumberBox<Integer> intBox = new NumberBox<>(10); // 가능
NumberBox<Double> doubleBox = new NumberBox<>(5.5); // 가능
// NumberBox<String> strBox = new NumberBox<>("Hello"); // 오류 발생 (String은 Number를 상속하지 않음)
}
}
5. 와일드카드(?)
와일드카드 ?를 사용하면 제네릭 타입을 정확히 알지 못하는 경우에도 사용할 수 있습니다.
public class Util {
// ?를 사용하여 모든 타입을 받을 수 있음
public static void printBox(Box<?> box) {
System.out.println(box.getItem());
}
}
public class Main {
public static void main(String[] args) {
Box<String> stringBox = new Box<>("Hello");
Box<Integer> intBox = new Box<>(100);
Util.printBox(stringBox); // 출력: Hello
Util.printBox(intBox); // 출력: 100
}
}
와일드카드의 종류
- <?> → 모든 타입 허용
- <? extends T> → T 또는 T의 하위 타입만 허용
- <? super T> → T 또는 T의 상위 타입만 허용
6. 제네릭 메서드
제네릭은 클래스뿐만 아니라 메서드에서도 사용할 수 있습니다.
public class Util {
// 제네릭 메서드 선언 (T는 메서드에서만 사용됨)
public static <T> void printItem(T item) {
System.out.println(item);
}
public static void main(String[] args) {
printItem("Hello"); // 출력: Hello
printItem(100); // 출력: 100
printItem(3.14); // 출력: 3.14
}
}
7. 제네릭 인터페이스
인터페이스에도 제네릭을 적용할 수 있습니다.
// 제네릭 인터페이스 선언
public interface Repository<T> {
void save(T item);
T find();
}
// String을 타입으로 지정한 구현 클래스
public class StringRepository implements Repository<String> {
private String data;
@Override
public void save(String item) {
this.data = item;
}
@Override
public String find() {
return data;
}
}
public class Main {
public static void main(String[] args) {
Repository<String> repo = new StringRepository();
repo.save("Generic Interface");
System.out.println(repo.find()); // 출력: Generic Interface
}
}
8. 제네릭과 배열
제네릭 타입의 배열을 직접 생성할 수는 없습니다.
T[] arr = new T[10]; // 컴파일 오류
대신 Object[]를 사용하거나 Array.newInstance()를 활용해야 합니다.
@SuppressWarnings("unchecked")
public class GenericArray<T> {
private T[] array;
public GenericArray(Class<T> clazz, int size) {
array = (T[]) java.lang.reflect.Array.newInstance(clazz, size);
}
public void set(int index, T value) {
array[index] = value;
}
public T get(int index) {
return array[index];
}
}
정리
✅ 제네릭 클래스는 타입을 파라미터화하여 재사용성을 높이고, 타입 안정성을 보장하는 기능
✅ 제네릭 메서드는 특정 메서드에서만 제네릭을 사용할 수 있도록 함
✅ **와일드카드(?)**를 사용하면 다양한 제네릭 타입을 유연하게 받을 수 있음
✅ **타입 제한(extends 사용)**을 통해 특정 타입만 사용하도록 제약 가능
✅ 제네릭 인터페이스를 활용하면 다양한 타입을 지원하는 인터페이스를 만들 수 있음
제네릭을 적절히 활용하면 유지보수성이 높은 코드를 작성할 수 있습니다. 😊
728x90
'개발 > 자바' 카테고리의 다른 글
| 전략 패턴(Strategy Pattern)과 방문자 패턴(Visitor Pattern) (0) | 2025.02.19 |
|---|---|
| Java instanceof 활용 및 문제점 (0) | 2025.02.19 |
| Java 5 가변 매개변수 (Varargs) (0) | 2025.02.19 |
| LocalDate 주요 메서드 정리 (0) | 2025.02.19 |
| SimpleDateFormat Thread-Safe 문제 (0) | 2025.02.19 |