제네릭(Generic)
뜻 자체는 일반적인.
제네릭(Generic)은 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 의미한다. 즉, 클래스 정의 시 특정(Specific) 타입을 미리 지정해주는 것이 아니라 인스턴스를 생성할 때 지정할 수 있도록 하는 일반(Generic) 타입이라는 것이다.

- 제네릭의 타입
| 타입 | 설명 |
| <T> | Type |
| <E> | Element |
| <K> | Key |
| <V> | Value |
| <N> | Number |
| <R> | Result |
사실 <>안의 알파벳은 한글자일 필요도 없고 설명과 맞춰 사용할 필요도 없으나 위와 같은 형태로 관례적으로 사용되고 있다.
- 제네릭을 왜 사용할까?
- 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.
- 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없다. 즉, 관리하기가 편하다.
- 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.
// 런타임시 에러
ArrayList list = new ArrayList(); //제네릭을 사용하지 않을경우
list.add("test");
String temp = (String) list.get(0); //타입변환이 필요함
// 컴파일시 에러
ArrayList<String> list2 = new ArrayList(); //제네릭을 사용할 경우
list2.add("test");
temp = list2.get(0); //타입변환이 필요없음
- 클래스 또는 인터페이스 선언 방법
public class 클래스명<T> {...}
public interface 인터페이스명<T> {...}
T타입은 해당 실행 블록안에서만 유효하며 타입 파라미터로 명시할 수 있는 것은 참조 타입 뿐이다. (기본 타입은 불가)
- 제네릭 클래스
class GenericExample<T> {
private T t;
public void setT(T t) {
this.t = t;
}
public T getT() {
return t;
}
}
- 제네릭 인터페이스
//인터페이스
interface InterfaceGenericExample<T> {
T example();
}
//구현 클래스
class GenericExample implements InterfaceGenericExample<String> {
@Override
public String example() {
return null;
}
}
- 제네릭 멀티 타입 파라미터 사용
2개 이상의 멀티 타입으로 사용한다.
class MultiGenericExample<K, V> {
private K key;
private V value;
@Override
public K getKey() {
return this.key;
}
@Override
public V getValue() {
return this.value;
}
@Override
public V setValue(V value) {
this.value = value;
return value;
}
}
이 방법을 사용하는 대표적인 예가 HashMap이다
public class HashMap <K, V> {...}
//----------------------------
HashMap<Integer,String> map = new HashMap<>();
map.put(1,"사과"); //값 추가
map.put(2,"바나나");
map.put(3,"포도");
- 제네릭 메소드
매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드
// 제네릭 메소드 선언
// 맨 앞에 사용 타입파라미터 선언, 리턴 타입: Box<T>, 매개 변수 타입: T
public <T> Box<T> boxing(T t) {
Box<T> box = new Box<T>();
box.set(t);
return box;
}
// 호출
public class BoxingMethodExample {
public static void main(String[] args) {
Box<Integer> box1 = <Integer> boxing(100);
int intValue = box1.get();
Box<String> box2 = boxing("홍길동");
String strValue = box2.get();
}
}
- 와일드 카드
모든 타입을 대신할 수 있는 타입을 와일드카드라고 하고 ? (물음표)로 표시하며 총 3가지 형태로 이용한다.
1) <?> : 모든 클래스나 인터페이스 타입이 올 수 있다.
public static void registerCourse(Course<?> course) {
System.out.println(course.getName() + " 수강생: " + Arrays.toString(course.getStudents()));
}
2) <? extends 상위타입> : 상한 경계 와일드 카드라 하며 와일드카드 타입의 최상위 타입을 정의하여 한계를 정한다.
아래 코드 같은 경우는 최상위 타입이 Student라 정해졌기 때문에 이와 동일하거나 그 이하의 타입만 ?에 들어올 수 있다.
public static void registerCourseStudent(Course<? extends Student> course) {
System.out.println(course.getName() + " 수강생: " + Arrays.toString(course.getStudents()) );
}
3) <? super 하위 타입> : 하한 경계 와일드 카드라 하며 와일드카드 타입의 최하위 타입을 정의하여 한계를 정한다.
아래 코드 경우 최하위 타입이 Worket라고 정해졌기 때문에 이와 동일하거나 그 이상인 타입만 ?에 들어올 수 있다.
public static void registerCourseWorker(Course<? super Worker> course) {
System.out.println(course.getName() + " 수강생: " + Arrays.toString(course.getStudents()));
}
- 제네릭 타입의 상속과 구현
제네릭 타입도 다른 타입과 마찬가지로 부모가 될 수 있으며 자식 클래스는 추가로 타입 파라미터를 가질 수 있다.
// 제네릭 타입의 상속
public class ChildProduct<T, M, C> extends Product<T, M> {...}
또한 인터페이스도 될 수 있으며 이를 구현한 클래스도 제네릭 타입이 된다.
// 제네릭 인터페이스
public interface Storage<T> {
//추상메소드
public void add(T item, int index);
}
// 제네릭 구현 클래스
public class StorageImpl<T> implements Storage<T> {
private T[] array;
public StorageImpl(int capacity) {
this.array = (T[]) (new Object[capacity]);
}
@Override
public void add(T item, int index) {
array[index] = item;
}
}
자바 [JAVA] - 제네릭(Generic)의 이해
정적언어(C, C++, C#, Java)을 다뤄보신 분이라면 제네릭(Generic)에 대해 잘 알지는 못하더라도 한 번쯤은 들어봤을 것이다. 특히 자료구조 같이 구조체를 직접 만들어 사용할 때 많이 쓰이기도 하고
st-lab.tistory.com
[Java] 제네릭과 와일드카드 타입에 대해 쉽고 완벽하게 이해하기(공변과 불공변, 상한 타입과 하
이번에는 공변과 불공변에 대해서 먼저 알아보고, 이후에 제네릭과 와일드카드에 대해 알아보도록 하겠습니다. 많은 분들이 어려워하는 제네릭인 만큼 쉽게 풀어서 설명하려고 노력했는데, 많
mangkyu.tistory.com
[Java]STEP2 - 2) 제네릭 메소드(Generic Method), 와일드카드, 제네릭 타입의 상속과 구현
본 게시글은 도서 "이것이 자바다" 동영상 강의를 듣고 기록하는 TIL(Today I Learned) 입니다. 모든 저작권은 출판사 한빛미디어와 신용권님께 있음을 알립니다.👍 이번 게시물은 저번 게시물에 이
kyleyj.tistory.com
제네릭 - 생활코딩
제네릭이란? 제네릭(Generic)은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다. 말이 어렵다. 아래 그림을 보자. 위의 그림은 아래의 코드를 간략화한 것이다. package or
opentutorials.org
'Programming > Java' 카테고리의 다른 글
| 혼공자바] 11 기본 API 클래스 (0) | 2022.12.14 |
|---|---|
| 혼공자바] 10-2 예외처리 (0) | 2022.12.13 |
| 혼공자바] 10-1 예외 클래스 (0) | 2022.12.12 |
| 혼공자바] 09-2 익명 객체 (0) | 2022.12.10 |
| 혼공자바] 09-1 중첩 클래스와 중첩 인터페이스 소개 (0) | 2022.12.09 |
