제네릭(Generic)이란 데이터의 타입을 '일반화'하는 것을 의미한다.
클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법이다. 클래스를 정의 할 때에는 데이터 타입을 확정하지 않고, 인스턴스를 생성할 때 데이터 타입을 지정하도록 한다.
🔹사용방법
제네릭 타입은 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다. 제네릭 타입은 클래스 또는 인터페이스 이름 뒤에 < > 부호가 붙고 부호 사이에 타입 파라미터가 위치한다.
public class 클래스명<T> {...}
public class 클래스명<T,S> {...} // 멀티 타입 파라미터
타입 파라미터는 정해진 규칙은 없지만 일반적으로 대문자 알파벳 한글자로 표현한다.
클래스를 설계할 때 구체적인 타입을 명시하지 않고 타입 파라미터로 넣어두었다가 실제 설계한 클래스가 사용되어질 때 구체적인 타입을 지정하면 타입 변환을 최소화 시킬 수 있다.
또한 제네릭은 참조 데이터 타입에 대해서만 사용할 수 있다. 기본 데이터 타입에서는 사용할 수 없기 때문에 참조 데이터 타입으로 변환해서 사용해야한다. 이 때 변환을 위해 사용하는 클래스를 래퍼(wrapper) 클래스라고 한다. 래퍼 클래스를 통해 제네릭에서 int와 같은 기본 데이터 타입을 사용할 수 있게 된다.
Integer i = new Integer(20);
🔹제네릭 와일드 카드의 타입
<?>: 타입 파라미터를 대체하는 것으로 모든 클래스나 인터페이스 타입을 사용할 수 있다.
<? extends 상위타입>: 와일드카드의 범위를 특정 객체의 하위 클래스만으로 한정한다.
<? super 하위타입>: 와일드카드의 범위를 특정 객체의 상위 클래스만으로 한정한다.
데이터 타입을 제네릭이 아닌 Object를 사용하면 모든 객체를 사용할 수 있게 된다. 그러나 모든 타입을 사용할 수 있기 때문에, 역으로 타입을 제한할 수도 없게 된다. 흐름에 맞지 않는 데이터 타입이 사용되더라도 컴파일 과정에서는 발견할 수 없다. 대신 동작 과정에서 런타임 에러가 발생하게 된다. 컴파일 언어는 모든 에러가 컴파일이 발생할 수 있도록 유도해야 한다. 이러한 에러를 타입에 대해 안전하지 않다고 표현한다.