1. 제네릭 - Generic1
제네릭 적용
제네릭을 사용하면 코드 재사용성과 타입 안정성이라는 두 마리 토끼를 한 번에 잡을 수 있다.
원하는 모든 타입 사용 가능
제네릭 클래스를 사용하면 다음과 같이 GenericBox
객체를 생성 시점(런타임)에 원하는 타입을 마음껏 지정할 수 있다.
참고로 제네릭을 도입한다고 해서 앞서 설명한 GenericBox<String>
, GenericBox<Integer>
와 같은 코드가
실제 만들어지는 것은 아니다.
대신에 자바 컴파일러가 우리가 입력한 타입 정보를 기반으로 이런 코드가 있다고 가정하고 컴파일 과정에 타입 정보를 반영한다. 이 과정에서 타입이 맞지 않으면 컴파일 오류가 발생한다.
타입 추론
첫번째 줄의 코드를 보면 변수를 선언할 때와 객체를 생성할 때 <Integer>
가 두 번 나온다.
자바는 왼쪽에 있는 변수를 선언할 때의 <Integer>
를 보고 오른쪽에 있는 객체를 생성할 때 필요한 타입 정보를 얻을 수 있다.
따라서, 두번째 줄의 오른쪽 코드 new GenericBox<>()
와 같이 타입 정보를 생략할 수 있다.
이렇게 자바가 스스로 타입 정보를 추론해서 개발자가 타입 정보를 생략할 수 있는 것을 "타입 추론" 이라 한다.
참고로 타입 추론이 그냥 되는 것은 아니고, 자바 컴파일러가 타입을 추론할 수 있는 상황에만 가능하다. 쉽게 이야기해서 읽을 수 있는 타입 정보가 주변에 있어야 추론할 수 있다.
제네릭 용어와 관례
제네릭의 핵심은 사용할 타입을 미리 결정하지 않는다는 점이다. 클래스 내부에서 사용하는 타입의 클래스를 정의하는 시점에 결정하는 것이 아니라, 실제 사용하는 생성 시점에 타입을 결정하는 것이다.
용어 정리
제네릭(Generic) 단어
제네릭이라는 단어는 일반적인, 범용적인이라는 영어 단어 뜻이다.
풀어보면 특정 타입에 속한 것이 아니라 일반적으로, 범용적으로 사용할 수 있다는 뜻이다.
제네릭 타입 (Generic Type)
클래스나 인터페이스를 정의할 때 타입 매개변수를 사용하는 것을 말한다.
제네릭 클래스, 제네릭 인터페이스를 모두 합쳐서 제네릭 타입이라 한다.
타입은 클래스, 인터페이스, 기본형(
int
등)을 모두 합쳐서 부르는 말이다.
예:
class GenericBox<T> { private T t; }
여기에서
GenericBox<T>
를 제네릭 타입이라 한다.
타입 매개변수 (Type Parameter)
제네릭 타입이나 메서드에서 사용되는 변수로, 실제 타입으로 대체된다.
예:
GenericBox<T>
여기에서
T
를 타입 매개변수라 한다.
타입 인자 (Type Argument)
제네릭 타입을 사용할 때 제공되는 실제 타입이다.
예:
GenericBox<Integer>
여기에서
Integer
를 타입 인자라 한다.
제네릭 명명 관례
타입 매개변수는 일반적인 변수명처럼 소문자로 사용해도 문제는 없다. 하지만 일반적으로 대문자를 사용하고 용도에 맞는 단어의 첫글자를 사용하는 관례를 따른다.
주로 사용하는 키워드는 다음과 같다.
E - Element
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types
제네릭 기타
다음과 같이 한번에 여러 타입 매개변수를 선언할 수 있다.
타입 인자로 기본형은 사용할 수 없다.
JVM 은 컴파일 후 타입 소거(ereaser) 를 하게 된다. 이렇게 되면 제네릭 타입 인자는 상한 제한이 있지 않는 경우
Object
로 치환되게 된다.하지만 객체인
Object
와 기본형 타입은 사용하는 메모리 구조가 다르기 때문에, 이를 허용해 줄 경우 JVM 메모리 사용의 어려움을 겪을 수 있다.레퍼런스 타입 : 힙 영역
기본형 타입 : 스택 영역
때문에, 제네릭의 타입 인자로 기본형( int
, double
..)은 사용할 수 없다. 대신에 래퍼 클래스( Integer
, Double
)를 사용 하면 된다.
int
, double
..)은 사용할 수 없다. 대신에 래퍼 클래스( Integer
, Double
)를 사용 하면 된다.Last updated