일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 다익스트라
- 유니온 파인드
- disjoint set
- 엔테크서비스
- Python
- 벨만 포드 알고리즘
- 기술면접
- dto
- 동적계획법
- Django
- bottom-up
- onclick
- clean code
- 음수가 포함된 최단경로
- kmeans
- 최단경로
- BufferedReader
- compiler
- scikit-learn
- 우선순위큐
- 직무면접
- 코딩테스트
- 플로이드 와샬
- Controller
- Java
- spring boot
- top-down
- Android Studio
- 거쳐가는 정점
- union-find
- Today
- Total
춤추는 개발자
[Java] 제네릭(generic)이란? 본문
✅ Generic
자바에서 제네릭(generic)이란, 데이터의 타입을 일반화(generalize)한다는 것을 의미한다. 쉽게 설명하자면 '데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 일반화하는 방법'이다.
이렇게 컴파일 시에 미리 타입 검사를 수행하면 다음과 같은 장점이 있다.
1. 클래스나 메서드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있다.
2. 반환값에 대해 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있다.
JDK 1.5 이전에서는 여러 타입을 사용하는 대부분의 클래스나 메서드에서 인수나 반환값으로 Object 타입을 사용해왔다. 하지만 반환된 Object 객체를 다시 원하는 타입으로 변환해야 하며, 이러한 상황에서 오류가 발생할 가능성도 존재한다.
이제 JDK 1.5 이후부터 도입된 제네릭(generic)은 클래스나 메서드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정한다. 그래서 타입 검사나 타입 변환과 같은 번거로운 작업을 생략할 수 있게 되었다.
[ 제네릭의 선언 및 생성 ]
class ExArray<T> {
T element;
void setElement(T element) { this.element = element; }
T getElement() { return element; }
}
자바에서 제네릭은 위와 같은 방법으로 클래스와 메서드에만 선언할 수 있다. 위 코드에서 사용된 'T'를 타입 변수(type variable)라고 하며, 임의의 참조형 타입을 의미한다. 타입 변수는 클래스뿐만 아니라 메서드의 매개변수나 반환값으로도 사용할 수 있다.
'T'뿐만 아니라 어떤 문자를 사용해도 상관없으며, 2개 이상의 타입 변수를 쉼표로 구분한다. 다만, 아래와 같이 타입에 따라 문자를 구분하여 사용하고 있다.
타입 | 설명 |
<T> | Type |
<E> | Element |
<K> | Key |
<V> | Value |
<N> | Numer |
위처럼 선언된 제네릭 클래스를 생성할 때에는 아래 코드처럼 타입 변수 자리에 사용할 실제 타입을 명시해야 한다.
ExArray<Integer> exArr = new ExArray<Integer>();
이처럼 클래스를 생성할 때 사용할 실제 타입을 명시하면, 내부적으로는 정의된 타입 변수가 명시된 실제 타입으로 변환되어 처리된다.
이번에는 제네릭에서 적용되는 타입 변수의 다형성을 보여주는 예제다.
class Avengers {
public void attack() { System.out.println("assemble"); }
}
class IronMan extends Avengers {
public void attack() { System.out.println("fire"); }
}
class Hulk extends Avengers {
public void attack() { System.out.println("smash"); }
}
class Thanos {
public void attack() { System.out.println("snab"); }
}
class HeroList<T> {
ArrayList<T> heros = new ArrayList<>();
void add(T hero) { heros.add(hero); }
T get(int index) { return heros.get(index); }
boolean remove(T hero) { return heros.remove(hero); }
int size() { return heros.size(); }
}
public class Generic {
public static void main(String[] args) {
HeroList<Avengers> avengers = new HeroList<>();
avengers.add(new Avengers());
avengers.add(new IronMan());
avengers.add(new Hulk());
// avengers.add(new Thanos());
for (int i = 0; i < avengers.size(); i++) {
avengers.get(i).attack();
}
}
}
// 결과
assemble
fire
smash
위 코드에서 IronMan과 Hulk 클래스는 Avengers 클래스를 상속받은 자식 클래스이므로 HeroList<Avengers>에 추가할 수 있다. 하지만, Thanos 클래스는 Avengers 클래스를 상속받지 않아 다른 타입으로 간주되어 추가할 수 없다.
'Developer's_til > 그외 개발 공부' 카테고리의 다른 글
[Design Pattern] 컴포지트 패턴(Composite Pattern)이란 (0) | 2021.12.31 |
---|---|
[Design Pattern] 템플릿 메서드 패턴(Template Method Pattern)이란 (0) | 2021.12.31 |
[Java] Lambda Expression(람다 표현식) (0) | 2021.12.27 |
웹훅[Webhook]이란 무엇일까? (0) | 2021.10.24 |
[Java] Stream API의 기본 메서드 - 2 (0) | 2021.07.30 |