클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법 - 객체별 다른 타입의 자료가 저장될 수 있도록 함
ArrayList<String> list = new ArrayList<>();
// <> : generic
// () : 타입명 기재
// -> 리스트 클래스 자료형의 타입 = String 타입으로 지정되어 문자열 데이터만 리스트에 적재 가능
1. 개념 예제

- generi은 배열의 타입을 지정하듯 리스트 자료형 같은 collection class나 method에서 사용할 내부 데이터 타입을 parameter 주듯이 외부에서 지정하는 이른바 타입을 변수화 한 기능
우리가 변수를 선언할 때 변수의 타입을 지정해주듯, generic은 객체(Object)에 타입을 지정해주는 것이라고 보면 된다
1-1. 수업 예제
// Generic = new하는 애가 처리
class Box<T> {
T data;
}
public class App {
public static <B> Box<?> test(B data) {
Box<B> b = new Box();
b.data = data;
return b;
}
public static void main(String[] args) {
Box b = test(1);
}
}
Type Parameter 기호 네이밍
타입 | 설명 |
<T> | 타입(Type) |
<E> | 요소(Element), Ex) List |
<K> | 키(Key), Ex) Map<k,v> |
<V> | Return 값 또는 매핑 된 값 (Variable) |
<N> | 숫자 (Number) |
<S, U, V> | 2, 3, 4번째 선언된 타입 |
2. Generic Type 매개변수

- 꺽쇠 괄호 안에 식별자 기호를 지정함으로써 파라미터화 가능
- 이것을 마치 method가 매개변수를 받아 사용하는 것과 비슷하여 Generic의 타입 매개변수(parameter) / 타입 변수라고 부름
2-1. Type Parameter 정의
- 이 타입 매개변수는 generic을 이용한 클래스나 메소드 설계 시 사용
class FruitBox<T> {
List<T> fruits = new ArrayList<>();
public void add(T fruit) {
fruits.add(fruit);
}
}
// generic 클래스 생성 후 인스턴스화 -> 파라미터를 지정해서 보내는 것처럼 생성 코드애서 꺽쇠 괄호 안에
// 지정해주고 싶은 타입명 할당 시, generic 클래스 선언문 부분으로 가서 타입 파라미터 T가 지정된 타입으로
// 모두 변환되어 클래스의 타입이 지정되게 되는 것
// generic 타입 매개변수에 정수 타입을 할당
FruitBox<Integer> intBox = new FruitBox<>();
// generic 타입 매개변수에 실수 타입을 할당
FruitBox<Double> intBox = new FruitBox<>();
// generic 타입 매개변수에 문자열 타입을 할당
FruitBox<String> intBox = new FruitBox<>();
// 클래스도 넣어줄 수 있음 (Apple 클래스가 있다고 가정)
FruitBox<Apple> intBox = new FruitBox<Apple>();
2-2. 그림 예제 (generic 타입 전파)

- <T> 부분에서 실행부에서 타입을 받아와 내부에서 <T> 타입으로 지정한 멤버들에게 전파하여 타입이 구체적으로 설정되는 것 → 구체화(Specialization)
2-3. Type Parameter 할당 가능 타입
- generic에서 할당 받을 수 있는 타입은 Reference 타입 뿐 → int형, double형 같은 자바 원시 타입(Primitive Type)을 generic type parameter로 넘길 수 없음
// 기본 타입 int는 사용 불가
List<int> intList = new List<>();
// Wrapper 클래스로 넘겨줘야 함 (내부에서 자동으로 언박싱되어 원시 타입으로 이용됨)
List<Integer> integerList = new List<>();
2-4. 복수 타입 Parameter
- 타입 지정이 여러개 필요할 경우 2, 3개 얼마든지 생성 가능
- generic 타입의 구분은 꺽쇠 괄호 안에서 쉼표(,)로 하며 <T, U>와 같은 형식을 통해 복수 타입 파라미터 지정 가능 (클래스 초기화 시 generic 타입을 2개 넘겨줘야 함)
import java.util.ArrayList;
import java.util.List;
class Apple {}
class Banana {}
class FruitBox<T, U> {
List<T> apples = new ArrayList<>();
List<U> bananas = new ArrayList<>();
public void add(T apple, U banana) {
apples.add(apple);
bananas.add(banana);
}
}
public class Main {
public static void main(String[] args) {
// 복수 generic 타입
FruitBox<Apple, Banana> box = new FruitBox<>();
box.add(new Apple(), new Banana());
box.add(new Apple(), new Banana());
}
}
3. Generic 사용 주의사항
3-1. generic 타입의 객체는 생성 불가
class Sample<T> {
public void someMethod() {
// Type parameter 'T' cannot be instantiated directly
T t = new T(); // new 연산자 뒤에 generic 타입 파리미터는 올 수 없음
}
}
3-2. static 멤버에 generic 타입이 올 수 없음
class Student<T> {
private String name;
private int age = 0;
// static 메서드의 반환 타입으로 사용 불가
// why? static 멤버는 클래스가 동일하게 공유하는 변수로서 generic 객체가 생성되기 전에,
// 이미 자료 타입이 정해져 있어야 하기 때문 -> 논리적 오류
public static T addAge(int n) {
}
// static 메소드의 매개변수 타입으로 사용 불가
// public static void addAge(T n) {
// }
}
3-3. generic으로 배열 선언 주의점
// 기본적으로 generic 클래스 자체를 배열로 만들 수 없음
class Sample<T> {
}
public class Main {
public static void main(String[] args) {
Sample<Integer>[] arr1 = new Sample<>[10];
}
}
// Error - java: cannot create array with '<>'
// generic 타입의 배열 선언은 허용됨
// 위의 식과 차이점 : 배열에 저장할 Sample 객체의 타입 파라미터를 Integer로 지정함
// -> new Sample<Integer>() 인스턴스는 저장이 가능, new Sample<Stirng>() 인스턴스는 저장이 불가능
class Sample<T> {
}
public class Main {
public static void main(String[] args) {
// new Sample<Integer>() 인스턴스만 저장하는 배열을 나타냄
Sample<Integer>[] arr2 = new Sample[10];
// generic 타입을 생략해도 위에서 이미 정의했기 때문에 Integer 가 자동으로 추론
arr2[0] = new Sample<Integer>();
arr2[1] = new Sample<>();
// ! Integer가 아닌 타입은 저장 불가능
arr2[2] = new Sample<String>();
}
}
Share article