본문 바로가기
Java

[Java] 제네릭(Generic) 이란?

by 태크민 2025. 1. 31.

제네릭 (Generics) 이란

자바에서 제네릭(Generics)은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다. 객체별로 다른 타입의 자료가 저장될 수 있도록 한다.

즉, 제네릭은 클래스와 인터페이스, 그리고 메소드를 정의할 때 타입(type) 파라미터(parameter)로 사용할 수 있도록 하며,

타입 파라미터는 코드 작성 시 구체적인 타입으로 대체되어 다양한 코드를 생성하도록 해준다.

 

자바에서 배열과 함께 자주 쓰이는 자료형이 리스트(List)인데, 다음과 같이 클래스 선언 문법에 꺾쇠 괄호 <> 로 되어있는 코드 형태를 한번 쯤은 봤을 것이다.

ArrayList<String> list = new ArrayList<>();

꺾쇠 괄호가 바로 제네릭이다. 괄호 안에는 타입명을 기재한다. 그러면 저 리스트 클래스 자료형의 타입은 String 타입으로 지정되어 문자열 데이터만 리스트에 적재할 수 있게 된다.

 

아래 그림과 같이 배열과 리스트의 선언문 형태를 비교해보면 이해하기 쉬울 것이다. 선언하는 키워드나 문법 순서가 다를뿐, 결국 자료형명을 선언하고 자료형의 타입을 지정한다는 점은 같다고 볼 수 있다.

 

이처럼 제네릭은 배열의 타입을 지정하듯이 리스트 자료형 같은 컬렉션 클래스나 메소드에서 사용할 내부 데이터 타입(type)을 파라미터(parameter) 주듯이 외부에서 지정하는 이른바 타입을 변수화 한 기능이라고 이해하면 된다.

우리가 변수를 선언할때 변수의 타입을 지정해주듯이, 제네릭은 객체(Object)에 타입을 지정해주는 것이라고 보면 된다.

 

타입 파라미터 정의

이 타입 매개변수는 제네릭을 이용한 클래스나 메소드를 설계할 때 사용된다.

예를들어 다음 코드는 제네릭을 감미한 클래스를 정의한 코드이다. 클래스명 옆에 <T> 기호로 제네릭을 붙여준 걸 볼 수 있다. 그리고 클래스 내부에서 식별자 기호 T 를 클래스 필드와, 메소드의 매개변수의 타입으로 지정되어 있다.

class FruitBox<T> {
    List<T> fruits = new ArrayList<>();

    public void add(T fruit) {
        fruits.add(fruit);
    }
}

제네릭 클래스를 만들었으면 이를 인스턴스화 해보자. 마치 파라미터를 지정해서 보내는 것 처럼 생성 코드에서 꺾쇠 괄호 안에 지정해주고 싶은 타입명을 할당해주면, 제네릭 클래스 선언문 부분으로 가서 타입 파라미터 T 가 지정된 타입으로 모두 변환되어 클래스의 타입이 지정되게 되는 것이다.

// 제네릭 타입 매개변수에 정수 타입을 할당
FruitBox<Integer> intBox = new FruitBox<>(); 

// 제네릭 타입 매개변수에 실수 타입을 할당
FruitBox<Double> intBox = new FruitBox<>(); 

// 제네릭 타입 매개변수에 문자열 타입을 할당
FruitBox<String> intBox = new FruitBox<>(); 

// 클래스도 넣어줄 수 있다. (Apple 클래스가 있다고 가정)
FruitBox<Apple> intBox = new FruitBox<Apple>();

이를 그림으로 표현해보면, 다음과 같이 제네릭 타입 전파가 행해진고 보면 된다. <T> 부분에서 실행부에서 타입을 받아와 내부에서 T 타입으로 지정한 멤버들에게 전파하여 타입이 구체적으로 설정 되는 것이다. 이를 전문 용어로 구체화(Specialization) 라고 한다.

 

 

 

제네릭의 장점

컴파일 시 강한 타입 체크를 할 수 있다. (타입 안정성)

컴파일 시 에러를 다 도출해내기 때문에 실행 중에 일어나는 에러(RuntimeException)를 방지할 수 있다.

// List Integer 타입으로 제네릭 타입 적용
List<Integer> list = new ArrayList();
list.add(1);
list.add("5"); // ERROR java: incompatible types: java.lang.String cannot be converted to java.lang.Integer

 

 

타입 변환을 제거한다.(casting)

다음 예시와 같이 제네릭을 사용하지 않는 경우 불필요한 타입 변환이 필요하게 된다.

따라서 프로그램 성능에 좋지 않은 영향을 미친다.

List list = new ArrayList();
list.add(1);

// 강제 형 변환 필요 
Integer number = (Integer) list.get(0);

 

물론 제네릭을 사용하지 않으면 다음과 같이 모든 종류의 객체를 저장할 수 있다.

1. Object 형태로 변환되어 List에 쌓인다.

이렇게 되면 저장할 때 타입 변환 발생,

2. 읽어올 때에도 타입 변환이 발생하게 된다.

List list = new ArrayList();
list.add(1);
list.add("5");
list.add(0.1);

Object o1 = list.get(0);
Object o2 = list.get(1);
Object o3 = list.get(2);

Integer num = (Integer) o1;
String str = (String) o2;
Long L = (Long) o3;

 

제네릭을 사용할 경우 List에 저장되는 요소를 Integer로 제한하기 때문에 get(index)할 경우 타입 변환이 필요가 없게 되어 프로그램 성능이 향상된다.

List<Integer> list = new ArrayList();
list.add(1);

// 형 변환 필요 없음
Integer number = list.get(0);

 


참고자료

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%A0%9C%EB%84%A4%EB%A6%ADGenerics-%EA%B0%9C%EB%85%90-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%B3%B5%ED%95%98%EA%B8%B0

 

☕ 자바 제네릭(Generics) 개념 & 문법 정복하기

제네릭 (Generics) 이란 자바에서 제네릭(Generics)은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다. 객체별로 다른 타입의 자료가 저장될 수 있도록 한다. 자바에서 배

inpa.tistory.com

https://veneas.tistory.com/entry/Java-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%82%AC%EC%9A%A9-%EC%9D%B4%EC%9C%A0-Why-do-use-Generic-in-Java

 

[Java] 제네릭 사용 이유 (Why do use Generic in Java?)

1. 제네릭의 등장 Java 5부터 Generic이라는 타입이 새로 추가되었습니다. 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거가 가능해졌습니다. 컬렉션, 람다, 스트림 등에서도 사용되므

veneas.tistory.com