티스토리 뷰
728x90
반응형
Bounded Wildcard (? extends T, ? super T)
제네릭의 타입 파라미터를 특정 범위로 제한하는 기능
와일드카드(?)를 사용하면 다양한 타입을 허용할 수 있지만, 어떤 타입까지 허용할지를 제어하기 위해 extends 또는 super를 사용
? extends T (상한 제한, Upper Bounded Wildcard)
import java.util.List;
import java.util.ArrayList;
class Animal {
void sound() {
System.out.println("동물이 소리를 냅니다.");
}
}
class Dog extends Animal {
void sound() {
System.out.println("멍멍!");
}
}
class Cat extends Animal {
void sound() {
System.out.println("야옹!");
}
}
public class UpperBoundWildcard {
// ? extends Animal → Animal과 그 하위 클래스만 허용
public static void printAnimalSounds(List<? extends Animal> list) {
for (Animal a : list) {
a.sound(); // ✅ 읽기(호출)는 가능
}
// list.add(new Dog()); ❌ 컴파일 오류 (쓰기 불가능)
}
public static void main(String[] args) {
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
List<Cat> cats = new ArrayList<>();
cats.add(new Cat());
printAnimalSounds(dogs); // ✅ 가능
printAnimalSounds(cats); // ✅ 가능
}
}
- T 또는 T의 하위 클래스만 허용
- 읽기(값 가져오기)는 가능하지만, 쓰기(값 추가)는 제한됨
- 하위 클래스 중 어떤 타입이 들어올지 정확하지 않기 때문
? super T (하한 제한, Lower Bounded Wildcard)
import java.util.List;
import java.util.ArrayList;
public class LowerBoundWildcard {
// ? super Integer → Integer와 그 상위 클래스 (Number, Object 등) 허용
public static void addNumbers(List<? super Integer> list) {
list.add(10);
list.add(20);
list.add(30);
// Integer 이하의 타입은 추가 가능
Object obj = list.get(0); // ✅ 읽을 때 Object 타입으로 처리
// Integer num = list.get(0); ❌ 컴파일 오류 (정확한 타입 알 수 없음)
}
public static void main(String[] args) {
List<Integer> intList = new ArrayList<>();
List<Number> numList = new ArrayList<>();
List<Object> objList = new ArrayList<>();
addNumbers(intList); // ✅ 가능
addNumbers(numList); // ✅ 가능
addNumbers(objList); // ✅ 가능
}
}
- T 또는 T의 상위 클래스만 허용
- 쓰기(값 추가)는 가능하지만, 읽기(값 가져오기)는 Object 타입으로 처리됨
- 어떤 상위 클래스가 올지 모르므로 정확한 타입을 보장할 수 없음
PECS(Producer Extends, Consumer Super)
? extends T (Producer) → 데이터를 제공할 때 (읽기 전용)
? super T (Consumer) → 데이터를 저장할 때 (쓰기 전용)
복사 유틸리티 메서드
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class PECSExample {
// `src` (데이터 제공) → `? extends T`
// `dest` (데이터 저장) → `? super T`
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (T item : src) {
dest.add(item); // ✅ 읽은 데이터를 저장
}
}
public static void main(String[] args) {
List<Integer> src = Arrays.asList(1, 2, 3, 4, 5);
List<Number> dest = new ArrayList<>();
copy(dest, src); // ✅ 가능 (Integer → Number)
System.out.println(dest); // 출력: [1, 2, 3, 4, 5]
}
}
- src에서 데이터를 읽을 때 → ? extends T 사용
- dest에 데이터를 쓸 때 → ? super T 사용
제네릭 정렬 메서드
import java.util.Collections;
import java.util.List;
public class SortExample {
// T가 Comparable을 구현한 타입이어야 함
public static <T extends Comparable<T>> void sortList(List<T> list) {
Collections.sort(list); // ✅ Comparable을 구현한 타입만 정렬 가능
}
public static void main(String[] args) {
List<Integer> numbers = List.of(5, 3, 8, 1, 2);
List<String> words = List.of("banana", "apple", "cherry");
// sortList(numbers); // ❌ List.of()는 Immutable List라 정렬 불가능
// sortList(words); // ❌ 마찬가지로 불가능
// ✅ Mutable List로 변경 후 사용
List<Integer> numList = new ArrayList<>(numbers);
List<String> wordList = new ArrayList<>(words);
sortList(numList);
sortList(wordList);
System.out.println(numList); // 출력: [1, 2, 3, 5, 8]
System.out.println(wordList); // 출력: [apple, banana, cherry]
}
}
- ? extends Comparable<T>를 사용하여 정렬 가능하도록 만듦
- List<T>가 Comparable을 구현하는지 확인
728x90
반응형
'Java' 카테고리의 다른 글
[Java] DIP (Dependency Inversion Principle) (0) | 2025.03.03 |
---|---|
[Java] Generic (0) | 2025.03.03 |
[Java] try-with-resources (0) | 2025.03.01 |
[Java] JSON Jackson @JsonProperty (0) | 2025.02.24 |
[Java] OpenCSV (0) | 2025.01.26 |
반응형
300x250