JAVA

[JAVA] 제네릭 < >

EJUN 2023. 5. 23. 14:02

제네릭<Generic>
주어진 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법
List<타입> list=new List<>();

위의 코드는 제네릭사용의 장점을 보여주는 코드이다.

제네릭을 사용하는 경우에는 <>괄호 사이에 사용하고 싶은 타입을 입력하면 사용할 수 있다.

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

위의 코드는 String 타입으로 list를 사용하겠다는 의미이다.

ArrayList에서 String타입을 이용하는 제네릭

ArrayList<String>으로 선언하면 ArrayList타입의 list변수는 String타입으로 사용한다는 의미이다.

ArrayList클래스는 List클래스를 상속받은 자식클래스이다.

 

 

제네릭 사용법

제네릭의 사용 방법은 다양한데 첫번째로 클래스 및 인터페이스 선언을 하는 경우에 제네릭을 사용하는 경우가 있다.

 


1. 클래스 및 인터페이스 선언

클래스 및 인터페이스 제네릭 선언

제네리클래스나 제네릭 인터페이스의 경우 위의 코드와 같이 선언을 해주는데

<T>가 의미하는 것은 T가 Type의 줄임말으로써 사용하는 타입을 의미하는 것이다.

즉, T자리에는 String,Integer,Boolean같은 타입이 올 수 있다.

제네릭 클래스

위 처럼 제네릭 클래스에 <T>로 타입을 지정하면 GenClass의 객체를 생성할 때 사용자가 지정해준 타입이 곧 T가 된다.

그래서 위처럼 제네릭 클래스를 생성하게 되면 타입의 변경이 용이하다는 장점이 있다.

 

GenClass타입을 String으로 지정

GenClass<String>으로 지정해주면 GenClass에서 T로 한 부분이 전부 String형으로 변경이 되어서 t.setAge("24")로 Age값을 문자열로 설정해주어야 한다.

제네릭 인터페이스도 제네릭 클래스과 똑같이 생성하고 호출할 때 타입을 지정해 주면 된다.

제네릭 인터페이스 타입 지정

또한 <T,K>처럼 아래의 사진처럼 두 개의 타입을 한번에 지정해 줄 수도 있다.

이중 타입의 제네릭 클래스
이중 타입의 제네릭 클래스 선언 방법

GenClass를 선언할 때 <T,K>처럼 2개의 타입을 지정할 수 있게 하였기 때문에 main()안에서 Integer, String의

Reference Type으로 지정해 주었기 때문에 위의 코드 처럼 사용할 수 있다.

 

그럼 Primitive Type은 사용할 수 없을까?

정답은 Yes이다.

왜냐하면 제네릭클래스<T>를 생성할 때는 객체를 생성하는 것이기 때문에 원시타입이 올 수 없다.

따라서 Integer,Double과 같은 참조타입을 사용한다.

 


2. 제네릭 메소드

<제네릭 타입> [반환타입] [메소드명]([반환타입] [매개변수])이 형태로 구성된다.

제네릭 메소드 구성 형식

여기서 중요한 점은 제네릭 클래스에서 선언한 타입과 제네릭 메소드에서 선언한 타입은 다르다라는 것이다.

제네릭 메소드와 제네릭 클래스 타입 차이

위의 코드를보면 GenClass의 타입은 Integer로 선언하여서 t.setAge에서 Age를 Integer타입인 24로 초기화를 하였다.

반면에 genericMethod()를 보면 String타입인 "junseok"으로 name이라는 변수를 초기화 한 것을 볼 수 있다.

이처럼 제네릭 클래스에서 선언한 타입과 제네릭메소드에서 사용하는 타입은 별개이다.

 

제네릭 < ? extends ?>, <? super ?>,<?>(와일드카드)

제네릭에는 범위를 개발자가 임의로 지정할 수 있는 방식이 3가지 있다.

우선 제한을 두지 않는 <?>와일드카드, 상한경계를 두는 < ? extends ?>, 하한경계를 두는 <? super ?>가 있다.

 

1. <T extends A>

<T extends A>는 상한경계를 의미하는데 쉽게 말해서 T는 A의 자손인 타입만 올 수 있다는 걸 의미한다.

클래스 상속도 예시

만약 클래스 구조가 위의 사진처럼 되어 있다.

<T extends A> //A, B, D 타입 가능
<T extends B> //B, D 타입 가능
<T extends C> //C, F, G 타입 가능 
<T extends D> //D타입만 가능

상한경계를 지정하게 되면 위의 클래스 구조에서 다음과 같이 T의 타입을 지정할 수 있다.

만약 제한한 범위의 타입을 사용하게 되면 오류가 발생한다.

 

2. <T super A>

<T super A>는 하한경계를 의미하는데 쉽게 말해서 T는 A의 부모 타입만 올 수 있다는 걸 의미한다.

위의 클래스 상속도를 기준으로 살펴보자.

<T super A> //A, GerericClass 타입 가능
<T super B> //A, B, GerericClass 타입 가능
<T super C> //C, GerericClass 타입 가능 
<T super GerericClass> //GerericClass 타입만 가능

위처럼 하한경계를 지정하게 되면 위의 클래스 구조에서 다음과 같이 T타입의 지정이 가능하다.

이 또한 제한한 범위를 벗어나게 되면 오류가 발생한다.

 

'JAVA' 카테고리의 다른 글

JAVA_단위 테스트&통합 테스트  (1) 2023.10.16
[JAVA] I/O스트림  (0) 2023.05.23
[JAVA] Enum(열거 타입)  (0) 2023.05.17
[JAVA] Thread & Runnable & Multi Thread란?  (0) 2023.05.03
[JAVA] 패키지&import & 접근 제어 지시자  (0) 2023.04.26