배경
같은 로직을 가지고, 두 타입의 자료를 다루는 경우를 생각해보자.
새우만 담을 수 있는 통과, 조개만 담을 수 있는 통이 있을 때 안에 들어있는 조개와 새우를 넣고 뺴는 행위(공통 로직)에는 변함이 없지만 통을 따로 나누어야만 한다.(코드의 분리) 하지만 따로 통에 들어갈 수 있는 해산물을 정하지 않고, 해산물 통으로 분류하고, 들어오는 해산물에 따라서 담는다면 편할 것이다.(코드의 재사용)
⇒ 제네릭의 사용으로 코드 재사용과 타입 안정성을 모두 잡을 수 있다.
제네릭의 핵심은 사용할 타입을 미리 정하지 않는다는 것이다.
제네릭
- 제네릭(Generic)
- 제네릭 타입(Generic Type)
- 클래스나 인터페이스를 정의할 때 타입 매개변수를 사용하는 것
- 타입 매개변수(Type Parameter)
- 제네릭 타입이다 메서드에서 사용되는 변수로, 실제 타입으로 대체된다.
- 타입 인자(Type Argument)
- 제네릭 타입을 사용할 때 제공되는 실제 타입
타입 매개변수 제한
기본적인 제네릭 타입으로 타입인자를 받을 경우, 제네릭 타입은 Object라면 모두 받을 수 있기 떄문에 타입을 제한할 수 없음
⇒ 제약을 걸어 사용을 가능하게 함. ex) T extends Animal
제네릭 메서드
- 정의 :
<T> T genenricMethod(T t) - 타입 인자 전달 : 메서드를 호출하는 시점
- 호출 :
GenericMethod.<타입 인자>genericMethod(i)타입 추론이 지원되기 때문에 매번 타입 인자를 적어주지 않아도 됨
와일드카드

와일드카드는 제네릭 타입, 제네릭 메서드를 선언하는 것이 아니다. 와일드카드는 이미 만들어진 제네릭 타입을 활용할 때 주로 사용한다.
제네릭 메서드와 와일드 카드의 사용 기준
기본적으로 사용하기 간단한 와일드 카드를 사용한다. 하지만 전달된 제네릭 타입 인자를 사용하거나 반환해야 하는 경우에는 제네릭 메서드를 사용해야 한다.
상한과 하한
- extends : 상한 지정
⇒
? extends Animal: Animal 하위 타입 지정 가능 - super : 하한 지정
⇒
? super Animal: Animal 상위 타입만 지정 가능 ex) Object
타입 이레이져
[!개념] 제네릭은 자바 컴파일 단계에서만 사용되고, 컴파일 이후에는 제네릭 정보가 삭제된다. ⇒
.java단계에서는 타입 매개변수가 존재하지만, 컴파일 이후 자바 코드인.class단계에서는 타입 매개변수가 존재하지 않는다.
컴파일 이전
public class GenericBox<Integer> {
private Integer value;
public void set(Integer value) {
this.value = value;
}
public Integer get() {
return value;
}
}컴파일 이후
public class GenericBox {
private Object value;
public void set(Object value) {
this.value = value;
}
public Object get() {
return value;
}
}상한 제한이 없는 경우 T는 Object로 모두 변환
타입 이레이져 방식의 한계
instanceof, new 사용 불가하다.