Monday
5. Java 고급 문법 (1) Generics 본문
제네릭(Generics) 깊이 있게 파헤치기
제네릭을 왜 배워야 할까?
- 타입 안전성 보장
- 코드 재사용성 증가
- 컴파일 시점 오류 검출
- 명시적 타입 캐스팅 불필요
제네릭의 본질: 타입의 유연성과 안전성
제네릭이란 무엇인가?
제네릭은 "타입을 파라미터화하여 컴파일 시점에 타입 안전성을 보장하는 Java의 강력한 기능"입니다.
제네릭 탄생 배경
Java 5 이전:
// 제네릭 이전 코드
List list = new ArrayList();
list.add("문자열");
list.add(123); // 어떤 타입이든 추가 가능
// 사용 시 강제 형변환 필요
String str = (String) list.get(0); // 런타임 시 오류 위험
제네릭 도입 후:
// 제네릭 적용
List<String> list = new ArrayList<>();
list.add("문자열");
// list.add(123); // 컴파일 에러 발생!
String str = list.get(0); // 안전한 타입 사용
제네릭의 심화 개념
1. 타입 매개변수의 다양한 표기법
제네릭에서 타입 파라미터를 선언할 때는 일반적으로 다음과 같은 순서와 관례를 따릅니다:
타입 파라미터 선언 순서
- 단일 타입 파라미터
<T>
: 가장 일반적으로 사용되는 타입 파라미터- 예:
class Box<T> { ... }
- 두 개 이상의 타입 파라미터
<K, V>
: 키-값 쌍에서 주로 사용- 예:
class Map<K, V> { ... }
- 제네릭 메서드에서 타입 파라미터는 메서드의 반환 타입 앞에 꺾쇠 괄호(<>)로 선언합니다
public static <E> void methodName(E[] parameter) { // 메서드 본문 }
일반적인 타입 파라미터 약속
기호 | 의미 | 주로 사용되는 곳 |
---|---|---|
T |
Type | 일반적인 타입 |
E |
Element | 컬렉션 요소 |
K |
Key | 맵의 키 |
V |
Value | 맵의 값 |
N |
Number | 숫자 타입 |
S , U , V |
2번째, 3번째, 4번째 타입 | 복수 타입 사용 시 |
예시:
class Pair<K, V> {
private K key;
private V value;
}
class MultiType<T, U, V> {
private T first;
private U second;
private V third;
}
2. 제네릭의 고급 사용법
바운디드 타입 파라미터
// Number의 하위 클래스만 허용
public class NumberBox<T extends Number> {
private T number;
public double sqrt() {
return Math.sqrt(number.doubleValue());
}
}
// 사용 예시
NumberBox<Integer> intBox = new NumberBox<>(); // 가능
NumberBox<String> strBox = new NumberBox<>(); // 컴파일 에러
와일드카드 활용
// 와일드카드의 3가지 형태
public class WildcardExample {
// 모든 타입 허용
public void printList(List<?> list) {
for (Object item : list) {
System.out.println(item);
}
}
// 특정 타입의 하위 클래스만 허용
public void processNumbers(List<? extends Number> numbers) {
// Number의 하위 클래스(Integer, Double 등)만 처리 가능
}
// 특정 타입의 상위 클래스만 허용
public void addNumbers(List<? super Integer> list) {
// Integer의 상위 클래스(Number, Object)만 처리 가능
}
}
3. T와 ?의 기본적인 차이
T (Type Parameter)
- 정의: 구체적인 타입을 지정할 수 있는 타입 파라미터
- 특징:
- 클래스나 메서드를 정의할 때 사용
- 실제 타입으로 대체 가능
- 사용자 정의 클래스도 타입으로 사용 가능
? (Wildcard)
- 정의: 알 수 없는 타입을 나타내는 와일드카드
- 특징:
- 타입이 불분명할 때 사용
- 제한된 유연성 제공
- 읽기 전용으로 주로 사용
예제로 이해하기
T 사용 예제
// 사용자 정의 클래스를 T로 사용 가능
class Person {}
class Student extends Person {}
class GenericBox<T> {
private T content;
public void setContent(T content) {
this.content = content;
}
public T getContent() {
return content;
}
}
// 사용
GenericBox<Person> personBox = new GenericBox<>();
GenericBox<Student> studentBox = new GenericBox<>();
? 사용 예제
class WildcardExample {
// 모든 타입의 리스트를 출력
public void printList(List<?> list) {
for (Object item : list) {
System.out.println(item);
}
}
// 특정 타입의 부모 클래스만 허용
public void processPersonList(List<? extends Person> list) {
// Person이나 Person의 자식 클래스 리스트만 처리 가능
for (Person person : list) {
// 처리 로직
}
}
}
주요 차이점
타입 지정
T
: 구체적인 타입 지정 가능?
: 타입 불분명, 제한된 접근
유연성
T
: 타입 안전성 높음?
: 더 유연한 타입 처리
메서드 사용
T
: 해당 타입의 메서드 호출 가능?
: Object 메서드만 호출 가능
4. 제네릭 메서드의 고급 패턴
public class GenericMethodExample {
// 제네릭 메서드: 타입 추론
public static <T> T getFirstElement(List<T> list) {
return list.isEmpty() ? null : list.get(0);
}
// 복수 타입 파라미터
public static <K, V> void printKeyValue(K key, V value) {
System.out.println("Key: " + key + ", Value: " + value);
}
// 제한된 타입 파라미터
public static <T extends Comparable<T>> T findMax(T a, T b) {
return (a.compareTo(b) > 0) ? a : b;
}
}
5. 제네릭의 제약사항
public class GenericLimitations<T> {
// 불가능한 연산들
// 1. 제네릭 타입으로 인스턴스 생성 불가
// T instance = new T(); // 컴파일 에러
// 2. 기본형 타입 사용 불가 (래퍼 클래스 사용)
// GenericBox<int> box = new GenericBox<>(); // 컴파일 에러
GenericBox<Integer> box = new GenericBox<>(); // 가능
// 3. 정적 멤버에 제네릭 타입 사용 불가
// private static T staticField; // 컴파일 에러
}
제네릭은 단순한 문법이 아니라 타입 시스템을 더욱 강력하고 유연하게 만드는 프로그래밍 패러다임입니다.
복잡해 보이지만, 결국 "타입에 대한 안전한 추상화"를 제공하는 Java의 혁신적인 기능입니다.
'언어 > Java' 카테고리의 다른 글
7. Java 예외 처리와 어노테이션 (0) | 2024.11.10 |
---|---|
6. Java 고급 문법 (2) 람다식과 Streams (0) | 2024.11.10 |
4. Java 객체지향 프로그래밍 (클래스, 상속, 다형성, 인터페이스) (1) | 2024.11.10 |
3. Java 참조 타입(스트링, 배열, enum) (0) | 2024.11.10 |
2. Java 기본 문법(데이터 타입, 변수, 제어문) (0) | 2024.11.10 |
Comments