자바 스터디

14주차 과제: 제네릭 +컬렉션

삶은겨란 2022. 6. 15. 22:57

목표

자바의 제네릭에 대해 학습하세요.

목차

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/황기태,김효수