14주차 과제: 제네릭 +컬렉션
목표
자바의 제네릭에 대해 학습하세요.
목차
1. 제네릭 사용법
2. 제네릭 주요 개념 (바운디드 타입, 와일드 카드)
3. 제네릭 메소드 만들기
4. Erasure
컬렉션
컬렉션(collection, collection framework) : 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합
데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓은 것.
컬렉션은 자바의 인터페이스를 사용하여 구현된다.
컬렉션의 장점
- 데이터 구조와 알고리즘 제공으로 프로그래밍 노력을 줄여줌(직접 작성할 필요가 없음)
- 성능 향상
- 관련 없는 API간의 상호 운용성을 제공
- API 학습, 설계, 구현을 하는 데 필요한 노력을 줄여줌
- 소프트웨어 재사용
컬렉션 인터페이스: 컬렉션을 나타내는 추상 데이터 유형
인터페이스 | 설명 |
Collection<E> | 컬렉션 계층의 루트. |
List<E> | 순서가 있는 데이터의 집합으로, 데이터의 중복을 허용함. |
Set<E> | 순서가 없는 데이터의 집합으로, 데이터의 중복을 허용하지 않음. |
Map<K, V> | 키와 값의 한 쌍으로 이루어지는 데이터의 집합으로, 순서가 없음. 이때 키는 중복을 허용하지 않지만, 값은 중복될 수 있음. |
Collection<E>의 메소드
메소드 | 설명 |
boolean add(E e) | 해당 컬렉션(collection)에 전달된 요소를 추가(선택적 기능) |
void clear() | 해당 컬렉션의 모든 요소를 제거(선택적 기능) |
boolean contains(Object o) | 해당 컬렉션이 전달된 객체를 포함하고 있는지를 확인 |
boolean equals(Object o) | 해당 컬렉션과 전달된 객체가 같은지를 확인 |
boolean isEmpty() | 해당 컬렉션이 비어있는지를 확인 |
Iterator<E> iterator() | 해당 컬렉션의 반복자(iterator)를 반환 |
boolean remove(Object o) | 해당 컬렉션에서 전달된 객체를 제거함(선택적 기능) |
int size() | 해당 컬렉션의 요소의 총 개수를 반환 |
Object[] toArray() | 해당 컬렉션의 모든 요소를 Object 타입의 배열로 반환 |
컬렉션 클래스: 컬렉션 인터페이스를 구현한 클래스로 개발자가 바로 사용 가능
클래스 | 설명 |
Vector<E> | 가변 크기의 배열 구현 |
ArrayList<E> | 가변 크기의 배열 구현 |
LinkedList<E> | 연결리스트 구현 |
Stack<E> | 스택 구현 |
HashSet<E> | 집합 구현 |
HashMap<K, V> | 키(K)와 값(V)의 쌍으로 이루어져 데이터를 저장하고 검색 |
컬렉션 특징
- 제네릭이란 기법으로 만들어져 있다.
<E>, <K>를 타입 매개변수라 하며, 특정 타입만 다루지 않고 여러 종류의 타입으로 사용할 수 있도록, 컬렉션을 일반화시키기위해 사용한 것. E를 일반화시킨 타입 또는 제네릭 타입이라 부른다.
- 컬렉션의 요소는 객체만 가능
Vector<int> v = new Vector<int>(); // 기본 타입은 사용 불가
Vector<Integer> v = new Vector<Integer>(); // 객체 사용
기본 타입을 사용하면 auto boxing에 의해 Wrapper 클래스 타입으로 변환되어 객체로 저장
1. 제네릭 사용법
제네릭(generic): 데이터 타입을 일반화하는 것(= c++의 템플릿)
제네릭은 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법
장점
- 클래스나 메소드 내부에서 사용되는 객체의 타입 안정성을 높인다.
- 반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄인다.
제네릭 선언 및 생성
public class MyClass<T>{ //타입 매개변수 T
T val; // 변수 val의 타입은 T
void set(T a){
val = a; // T타입의 값 a를 val에 지정
}
T get(){
return val; // T타입의 값 val 리턴
}
}
타입변수는 T말고 다른 문자를 사용해도 되지만 관례적으로 사용하는 대문자가 있다.
(E: element, T: type, V: value, K: key)
제네릭 클래스를 생성할 때는 객체를 사용한다.(컬렉션과 같음)
MyArray<Integer> myArr = new MyArray<Integer>();
2. 제네릭 주요 개념 (바운디드 타입, 와일드 카드)
바운디드 타입: 타입 변수에 특정 타입만 사용하도록 제한 한다.
class Calc<T extends Number> { // Number의 자손만 타입으로 지정할 수 있다
}
주의) 클래스, 인터페이스 둘 다 extends를 사용한다.
와일드카드: 이름에 제한을 두지 않음. ?로 표시
<?> // 타입 변수에 모든 타입을 사용할 수 있음.
<? extends T> // T 타입과 T 타입을 상속받는 자손 클래스 타입만을 사용할 수 있음.
<? super T> // T 타입과 T 타입이 상속받은 조상 클래스 타입만을 사용할 수 있음.
3. 제네릭 메소드 만들기
제네릭 메소드: 선언부에 타입 변수를 사용한 메소드
class GenericMethod{
static <T> void toStack(T[] a, GStack<T> gs){
for(int i=0; i<a.length; i++){
gs.push(a[i]);
}
}
}
타입 변수는 리턴 타입 앞에 선언한다.
String[] sArray = new String[100];
GStack<String> stringStack = new GStack<String>();
GenericMethod.toStack(sArray, stringStack);
다음 코드에서 컴파일러가 toStack()의 호출문으로부터 타입변수 T를 String으로 유추한다.
제네릭 메소드를 호출할 때는 컴파일러가 메소드의 인자를 통해 타입을 유추할 수 있어 제네릭 클래스나 인터페이스와 달리 타입 명시를 하지 않아도 된다.
GenericMethod.toStack(sArray, objectStack);
sArray는 String[] 타입이고, objectStack은 GStack<Object>인 경우, Object가 String의 슈퍼 클래스이므로 컴파일러는 Object 타입으로 유추한다.
주의) 제너릭 클래스와 T와 제너릭 메소드의 T는 다르다.
4. Erasure
제너릭 타입 제거
컴파일러는 제너릭으로 이용해 소스파일을 체크, 형 변환 후 제너릭 타입을 제거한다.
.class 파일에는 제너릭 타입이 없다.
http://www.tcpschool.com/java/java_collectionFramework_concept
https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html
https://docs.oracle.com/javase/tutorial/collections/index.html
http://www.tcpschool.com/java/java_generic_concept
http://www.tcpschool.com/java/java_generic_various
명품 JAVA Programming/황기태,김효수