코딩/Java

제네릭

제네릭은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다.

 

제네릭 사용법

위 코드의 p.infor와 p2.infor의 데이터 타입은 결과적으로 아래와 같다.

p1.infor : String

p2.infor : Stringbuilder

각각의 인스턴스를 생성할 때 사용한 < > 사이에 어떤 데이터 타입을 사용했느냐에 달려있다.

 

제네릭의 사용 이유 :

 

위의 코드는 StudentPerson과 EmployyPerson가 사실상 같은 구조를 가지고 있다 중복이 발생하고 있는 것이다. 중복을 제거해보자.

 

클래스 Person의 생성자는 매개변수 info의 데이터 타입이 Object이다. 따라서 모든 객체가 될 수 있다. 그렇기 때문에 위와 EmployeeInfo의 객체가 아니라 String이 와도 컴파일 에러가 발생하지 않는다. 대신 런타임 에러가 발생한다. 컴파일 언어의 기본은 모든 에러는 컴파일이 발생할 수 있도록 유도해야 한다는 것이다. 런타임은 실제로 애플리케이션이 동작하고 있는 상황이기 때문에 런타임에 발생하는 에러는 항상 심각한 문제를 초래할 수 있기 때문이다. 

위와 같은 에러를 타입에 대해서 안전하지 않다고 한다. 즉 모든 타입이 올 수 있기 때문에 타입을 엄격하게 제한 할 수 없게 되는 것이다. 

 

타입이 안전하지 않는 문제를 해결하기 

Person이 StudentInfoPerson과 EmployyPerson처럼 나누어져 있을 때는 타입이 안전하다는 장점이 있었다.

코드의 중복을 제거하면 편의성은 있지만 타입이 안전하지 않다는 문제가 있다. 이 두마리 토끼를 잡기위해 도입된 기능이 제네릭이다.

 

p1은 잘 동작할 것이다. 중요한 것은 p2다. p2는 컴파일 오류가 발생하는데  p2.info가 String이고 String은 rank 필드가 없는데 이것을 호출하고 있기 때문이다. 여기서 중요한 것은 아래와 같이 정리할 수 있다.

 

컴파일 단계에서 오류가 검출된다.
중복의 제거와 타입 안전성을 동시에 추구할 수 있게 되었다.

 

 

복수의 제네릭 :

 

제네릭<>에는 참조 데이터 타입만이 올 수 있다. 즉 기본데이터 타입(int, char, double ..)은 불가능하다.

이 기본 데이터 타입을 사용하기 위해 레퍼 데이터 타입을 쓰면 된다. 기본 데이터 타입을 마치 객체인 것처럼 만들 수 있는 객체를 제공한다. 이를 레퍼 클래스라 한다. int는 Integer, double는 Double .. 등이 있다.

 

기본 데이터 타입과 제네릭 :

 

new Integer는 기본 데이터 타입인 int를 참조 데이터 타입으로 변환해주는 역할을 한다. 이러한 클래스를 래퍼(wrapper) 클래스라고 한다. 덕분에 기본 데이터 타입을 사용할 수 없는 제네릭에서 int를 사용할 수 있다.

 

제네릭의 생략 :

 

 

EmployeeInfo e = new EmployeeInfo(1);
int i = 10;

이렇게 e와 i가 어떤 타입인지 알고 있을 때

Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);

위의 코드에 <>를 생략할 수 있다 왜냐하면 e, i의 데이터 타입을 이미 알고 있기 때문이다.

 

제레닉은 메소드로도 사용 가능하다. 

 

 

제네릭의 제한 :

 

즉 Person의 T는 Info 클래스나 그 자식 외에는 올 수 없다.

extends는 상속(extends)뿐 아니라 구현(implements)의 관계에서도 사용할 수 있다.

 

interface

interface로 했는데 Person이 왜 implements가 아닌 extends인 것이 의문일 것이다.

extends는 제네릭안에서 사용될 때는 상속이 아니라 부모가(Info의 부모) 누구인지 가르키기 때문이다.

'코딩 > Java' 카테고리의 다른 글

Collections framework2  (0) 2021.01.11
Collections framework  (0) 2021.01.11
참조와 복제  (0) 2021.01.09
상수와 enum2  (0) 2021.01.09
상수와 enum  (0) 2021.01.08