제네릭 보충자료
제네릭이 필요한 이유
(1) 동일한 기능, 다른 타입
동일한 로직을 처리하지만, 타입이 다를 경우 매번 새로운 메서드를 생성해야 합니다.
문제점
class Printer {
void printString(String str) {
System.out.println("String: " + str);
}
void printInteger(Integer num) {
System.out.println("Integer: " + num);
}
}위 코드처럼 각 타입별로 메서드를 정의하면 중복 코드가 발생합니다.
(2) 다형성으로 해결
Object 타입을 사용하면 다형성을 이용하여 타입을 처리할 수 있습니다.
문제점
타입 안정성 부족: 잘못된 타입을 캐스팅할 경우 런타임 오류가 발생할 수 있습니다.
컴파일 단계에서 이러한 오류를 잡아낼 수 없습니다.
(3) 제네릭으로 해결
제네릭을 사용하면 컴파일 시 타입을 체크하여 런타임 오류를 방지할 수 있습니다.
코드 재사용성과 타입 안정성을 동시에 보장합니다.
제네릭을 사용한 해결 코드
실행 결과
제네릭의 기본 특징
(1) 기본형은 제네릭 타입으로 사용할 수 없다
제네릭은 참조형 타입만 사용 가능합니다.
기본형 데이터 타입(
int,double등)을 사용하려면 래퍼 클래스(Integer,Double)로 변환해야 합니다.
코드 예시
(2) <> 없이 사용 가능 (원시 타입, Raw Type)
제네릭 타입을 선언하지 않으면 Object 타입으로 처리됩니다.
문제점:
타입 안정성이 보장되지 않아, 잘못된 타입 사용 시 런타임 오류가 발생할 수 있습니다.
코드 예시
2. 타입 매개변수 제한
(1) extends로 제한
extends로 제한타입 매개변수를 특정 타입 또는 특정 타입의 하위 클래스만 허용하도록 제한할 수 있습니다.
T extends Type:T는Type클래스 또는 그 하위 클래스만 허용됩니다.
코드 예시
3. 제네릭 메서드
(1) 정의와 특징
정의:
반환 타입 앞에 **
<T>**와 같은 타입 매개변수를 선언하여 제네릭 메서드를 정의합니다.메서드 호출 시점에 타입이 결정됩니다.
특징:
인스턴스 메서드와 static 메서드 모두 적용 가능합니다.
메서드 내부에서만 타입 매개변수가 적용됩니다.
(2) 예제: 캐스팅 없이 타입 반환
코드 예시
(3) 타입 제한이 있는 제네릭 메서드
코드 예시
(4) 제네릭 메서드의 타입 추론
컴파일러는 전달된 인자를 기반으로 타입을 추론합니다.
코드 예시
4. 제네릭 클래스와 제네릭 메서드의 차이
구분
제네릭 클래스
제네릭 메서드
타입 결정 시점
객체를 생성하는 시점
메서드를 호출하는 시점
범위
클래스 전체에서 타입 매개변수 사용 가능
메서드 내부에서만 타입 매개변수 사용 가능
적용 방식
class Box<T>
public static <T> void method(T value)
코드 예시
5. 정리
제네릭 클래스:
객체 생성 시점에 타입을 결정.
동일한 로직을 여러 타입에서 재사용 가능.
제네릭 메서드:
메서드 호출 시점에 타입을 결정.
캐스팅 없이 입력된 타입 그대로 반환 가능.
타입 제한:
extends키워드를 사용해 허용된 타입 범위를 설정.컴파일 단계에서 타입 오류를 방지.
와일드카드 (Wildcard)
1. 와일드카드란?
정의: 와일드카드는 제네릭의 유연성을 높이기 위해 사용되며, **
?**로 표현됩니다.목적:
특정 타입에 한정되지 않고, 여러 타입을 처리할 수 있도록 제네릭을 확장.
이미 만들어진 제네릭 클래스나 메서드를 활용할 때 사용.
코드 설명:
Box<T>클래스:제네릭 클래스로, 타입에 따라
item을 저장합니다.타입 안정성을 제공하며, 타입 캐스팅 없이 사용할 수 있습니다.
printBoxContents메서드:와일드카드
<? extends Number>를 사용하여Number타입의 하위 클래스만 허용합니다. 즉,Integer,Double,Float등이 가능합니다.리스트 안의 값을 출력합니다.
와일드카드의 유연성:
printBoxContents는 타입을 명시적으로 지정하지 않고Integer와Double두 타입 모두를 처리할 수 있습니다.특정 타입만 허용하려는 경우, 와일드카드로 제한을 설정 (
extends또는super)할 수 있습니다.
실행 결과:
2. 와일드카드와 제네릭의 차이점
구분
제네릭
와일드카드
사용 대상
새로 정의하는 클래스나 메서드
이미 만들어진 제네릭 클래스나 메서드 활용
표현 방법
타입 매개변수(T, E 등) 사용
? 사용
역할
타입 안정성을 유지하면서 동적인 타입 처리
타입 제한 없이 더 유연한 처리 가능
3. 와일드카드의 타입 제한
(1) 제한 없는 와일드카드 (<?>)
<?>)어떤 타입이든 허용.
코드 예시
(2) 상한 제한 와일드카드 (<? extends Type>)
<? extends Type>)와일드카드로
Type클래스 또는 하위 클래스만 허용.
코드 예시
(3) 하한 제한 와일드카드 (<? super Type>)
<? super Type>)와일드카드로
Type클래스 또는 상위 클래스만 허용.
코드 예시
4. 와일드카드의 특징과 주의점
동적 타입 반환이 아님:
와일드카드는 반환 타입을 변경하거나 동적으로 처리하지 않습니다.
반환되는 객체는
Object로 처리되거나 명시적 캐스팅이 필요합니다.
제네릭과 함께 사용:
새롭게 정의된 제네릭보다는 이미 만들어진 제네릭 클래스/메서드 활용에 적합.
타입 이레이저 (Type Erasure)
1. 타입 이레이저란?
정의: 자바의 제네릭은 컴파일 시점에만 타입을 체크하며, 컴파일 후에는 모든 제네릭 정보가 제거됩니다.
목적:
하위 호환성을 유지하면서도 타입 안정성을 제공.
특징:
컴파일 후 모든 타입 매개변수(
T,E)는 **Object**로 변환.타입 매개변수가 **
extends**로 제한되었을 경우, 제한된 타입으로 변환.
2. 타입 이레이저의 동작
컴파일 전:
컴파일 후:
3. 타입 이레이저의 주의점
타입 정보 소실:
제네릭의 타입 매개변수는 컴파일 시점에만 사용되고, 컴파일 이후에는 제거됩니다.
T를 사용한 인스턴스 생성 불가:
컴파일 이후 타입 정보가 사라지므로
new T()와 같은 인스턴스 생성은 불가능합니다.
코드 예시: 컴파일 오류
4. 예제: 타입 이레이저 동작
(1) 제네릭 클래스 컴파일 후 동작
(2) extends를 활용한 타입 제한
extends를 활용한 타입 제한코드 예시
5. 정리
와일드카드
와일드카드(
?):제네릭보다 더 유연하게 이미 만들어진 클래스를 활용 가능.
타입 제한:
<? extends Type>: 상한 제한.<? super Type>: 하한 제한.
타입 이레이저
컴파일 시점에서만 타입 체크:
컴파일 완료 후 제네릭 정보 제거.
모든 타입 매개변수는 Object로 변환.
주요 특징:
extends로 타입 제한 시, 제한된 타입으로 변환.컴파일 이후 제네릭 타입 정보가 없으므로
new T()불가.
Last updated