Java - 제네릭(Generic)
- 제네릭(Generic)은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 말한다.
| 1 | class Person<T>{ | 
- 위와 같이 사용한다면 외부에서 생성한 객체의 타입을 <>에 정의함으로써 Person클래스의 info라는 필드의 타입이 정의되는 것이다.- p1으로 객체를 생성한다면 info의 데이터 타입은 String이 되는 것이고,
- p2로 객체를 생성한다면 info의 데이터 타입은 StringBuilder이 되는 것이다.
 
- <T>의 위치에는 레퍼런스 형만 올 수 있고, 기본 데이터 타입((primitive type) => int, char 등..)은 제네릭으로 사용할 수 없다.(기본 데이터 타입은 객체가 아님)
- 따라서, 기본 데이터 타입을 객체인 것처럼 만들 수 있는 객체를 제공하는 wrapper 클래스를 사용한다.- int -> Integer,- double -> Double…와 같이 사용
- Integer id = new Integer(1);와 같이 생성하여 생성자의 매개변수로 넘길 수 있다.
- p1.id.intValue()와 같이 wrapper 클래스(Integer)의 메서드를 사용하여 wrapper 클래스가 담고 있는 원시 데이터 타입으로 반환 받을 수 있다.
 
제네릭의 생략
- 다음과 같은 경우 제네릭은 생략 가능하다.1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15class Person<T, S>{ 
 public T info;
 public S id;
 Person(T info, S id){
 this.info = info;
 this.id = id;
 }
 }
 public class GenericDemo {
 public static void main(String[] args) {
 EmployeeInfo ei = new EmployeeInfo(1);
 Integer id = 10;
 Person p1 = new Person(ei, id);
 }
 }
- 이 경우, 이미 ei와 id의 타입을 자바가 알고 있기 때문에 제네릭을 생략할 수 있다.
제네릭의 제한
- <T extends Info>와 같은 형태로 사용- Info클래스 또는 인터페이스를 상속받는 클래스의 데이터 타입인 경우로 제한한다.- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27- abstract class Info{ 
 public abstract int getLevel();
 }
 class EmployeeInfo extends Info{
 public int rank;
 EmployeeInfo(int rank){
 this.rank = rank;
 }
 public int getLevel(){
 return this.rank;
 }
 }
 class Person<T extends Info>{
 public T info;
 Person(T info){
 this.info = info;
 }
 }
 public class GenericDemo {
 public static void main(String[] args) {
 Person<EmployeeInfo> p1 = new Person<EmployeeInfo>(new EmployeeInfo(1));
 Person<String> p2 = new Person<String>("부장"); // 이 경우에는 에러
 }
 }
 
- Person<EmployeeInfo> p1 = new Person<EmployeeInfo>(new EmployeeInfo(1));와 같이- Info를 상속받는- EmployeeInfo타입인 경우에는 정상적으로 사용이 가능하지만
- Person<String> p2 = new Person<String>("부장");와 같이- String타입인 경우 에러가 발생하게 된다.
- 즉, class Person<T extends Info>{에서 T에는 Info 클래스 혹은 그 자식만이 올 수 있다.
- abstract class Info{같은 경우 추상 클래스가 아니라 일반 클래스 혹인 인터페이스인 경우에도 동일하다.- Info가 인터페이스라고 해서- T extends Info>의 부분이 implements로 변한다거나 하지는 않는다.
 
제네릭의 장점
- 타입 안정성을 제공한다.(의도하지 않은 타입의 객체를 저장하는 것을 막고, 저장된 객체를 꺼내올 때 원래의 타입과 다른 타입으로 형변환하여 발생할 수 있는 오류를 줄인다.)
- 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다.- 다룰 객체의 타입을 미리 명시함으로써 형변환을 하지 않아도 되도록 하는 것이다.
- 기존에는 다양한 종류의 타입을 다루는 메서드의 매개변수나 리턴 타입으로 Object타입의 참조 변수를 많이 사용했고, 그로 인해 형변환이 불가피했지만, 이젠 Object타입 대신 원하는 타입을 지정해주기만 하면 되는 것이다.
 
참조
https://devbox.tistory.com/entry/Java-%EC%A0%9C%EB%84%A4%EB%A6%AD
https://www.youtube.com/watch?v=YUinFIexEQ4
