출처 - Java의 정석 기초편 (남궁 성)
1. 지네릭스
- 컬렉션 클래스 컴파일시 타입 체크 해주는 기능(compile-time type check)-JDK 1.5
- 컴파일러 한계: 실행시 에러(형변환 에러)→컴파일 에러→지네릭스 도입
- 장점: 타입 안정성 제공, 타입 체크와 형변환 생략 가능
// Tv객체만 저장할 수 있는 ArrayList 생성
ArrayList <Tv> tvList = new ArrayList<Tv>(); // 타입 지정
tvList.add(new Tv()); //
tvList.add(new Audio()); // 컴파일 에러, Tv 타입 외 저장 불가
Tv t = tvList.get(0); // 저장된 객체 꺼낼 때 Object가 아닌 Tv 반환 → 형변환 불필요
2. 타입 변수(type variable)
- 타입 변수 <E> 선언하고 일반 클래스 Object → E 변경
- 타입 변수 여러개면 콤마(,)로 구분: Map<K, V>
// 지네릭 클래스 작성시 Object 타입 대신 타임 변수 E 선언
public class ArrayList<E> extends AbstractList<E> { // 일부 생략
private transient E[] elementData;
public boolean add(E o) { /* 생략 */ }
public E get(int index) { /* 생략 */ }
...
}
// 객체 생성시 타입 변수 E 대신 실제 타입 대입
ArrayList<Tv> tvList = new ArrayList<Tv>(); // 참조변수, 생성자에 실제 타입 Tv 대입
3. 지네릭스 용어
class Box<T> {}
// 지네릭 클래스: Box<T>
// 타입 변수, 타입 매개변수: T
// 원시 타입(일반 클래스): Box
Box<String> b = new Box<String>();
// 지네릭 타입 호출: Box<String>
// 대입된 타입(parameterized type): String
// 컴파일 후 지네릭 타입 제거되어 원시 타입 Box로 바뀜
4. 지네릭 타입 다형성
- 참조변수와 생성자에 대입된 타입 일치
- 클래스 타입 간 다형성은 성립(대입된 타입 일치)
- 매개 변수의 다형성도 성립
ArrayList<Tv> list = new ArrayList<Tv>(); // ok
ArrayList<Product> list = new ArrayList<Tv>(); // 상속 관계라도 불일치 에러
List<Tv> list = new ArrayList<Tv>(); // ok
ArrayList<Product> list = new ArrayList<Product>();
list.add(new Product());
list add(new Tv()); // ok
list add(new Audio()); // ok
// boolean add(Product e) {...} // Product와 그 자손 객체 가능
Product p = list.get(0); // 형변환 불필요
Tv t = (Tv)list.get(1); // 형변환 필요
// Product get(int index) {...} // 반환타입 Product
5. Iterator<E>
- 지네릭스 적용
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
// E → Student 대입
Iterator<Student> it = list.iterator();
while (it.hasNext()) {
Student s = it.next(); // Student 반환 → 형변환 불필요
}
6. HashMap<K, V>
- 타입 변수 여러개면 콤마(,)로 구분(n개 가능)
public class HashMap<K, V> extends AbstractMap<K, V> { // 일부 생략
public V get(Object key) { /* 생략 */ }
public V put(K key, V value) { /* 생략 */ }
public V remove(Object key) { /* 생략 */ }
}
HashMap<String, Student> map = new HashMap<String, Student>(); // 생성
map.put("레이", new Student("레이", 1, 1, 100, 100, 100)); // 저장
Student s1 = map.get("1-1"); // 반환타입 Student → 형변환 불필요
7. 제한된 지네릭 클래스
- T 모든 타입 가능 → extends로 타입 제한
- 인터페이스도 extends 사용
class FruitBox<T extends Fruit> { // Fruit(포함) 자손만 타입 지정 가능
ArrayList<T> list = new ArrayList<T>();
}
FruitBox<Apple> appleBox = new FruiitBox<Apple>(); // ok
interface Eatable {}
class FruitBox<T extends Fruit & Eatable> {...} // implements 사용 안함
8. 지네릭스 제약
- 인스턴스별로 타입 변수 다르게 지정 가능
- static 멤버에 타입 변수 사용 불가(T는 인스턴스 변수 간주)
- 객체, 배열 생성시 타입 변수 사용 불가(new 연산자 다음 T 불가)
Box<Apple> appleBox = new Box<Apple>(); // ok
Box<Grape> grapeBox = new Box<Grape>(); // ok
class Box<T> {
static T item; // 에러
static int compare(T t1, T t2) {...} // 에러
T [] tmpArr = new T[itemArr.length]; // 에러
}
9. 와일드 카드<?>
- 와일드 카드의 상한 → T와 그 자손들: <? extends T>
- 와일드 카드의 하한 → T와 그 조상들: <? super T>
- 제한 없음 → 모든 타입 가능: <?> == <? extends Object>
- 지네릭 타입 다형성: 하나의 참조 변수로 대입된 타입이 다른 객체 참조 가능
- 메서드의 매개 변수에 와일드 카드 사용
ArrayList<? extends Product> list = new ArrayList<Tv>(); // ok
ArrayList<? extends Product> list = new ArrayList<Audio>(); // ok
10. 지네릭 메서드
- 지네릭 타입이 선언된 메서드(타입 변수는 메서드 내에서만 유효)
- 클래스의 타입 매개변수 <T>와 메서드의 타입 매개변수 <T>는 별개
- 메서드를 호출할 때마다 타입 대입→대부분 생략 가능
class FruitBox<T> { // 지네릭 클래스
static <T> void sort(List<T> list, comparator<? super T> c) { // 지네릭 메서드
...
}
}
11. 지네릭 타입 형변환
- 지네릭 타입과 원시 타입 간 형변환 가능, 경고 발생
- 대입된 타입이 다른 지네릭 타입 간 형변환 불가능
- 와일드 카드가 사용된 지네릭 타입으로는 형변환 가능
// 지네릭 타입 ↔ 원시 타입: 형변환 가능, 경고 발생
box = (Box)objBox;
objBox = (Box<Object>)box;
// 대입된 타입이 다른 지네릭 타입 간: 형변환 불가능
objBox = (Box<Object>)strBox; // 에러
strBox = (Box<Strign>)objBox; // 에러
// 와일드 카드 사용된 지네릭 타입: 형변환 가능 → 생략됨
FruitBox<? extends Fruit> box = new FruitBox<Fruit>;
FruitBox<? extends Fruit> box = new FruitBox<Apple>();
12. 지네릭 타입 제거
- Java 하위호환성 유지: 컴파일시 <T>→Object 또는 적절한 타입
- 지네릭 타입 제거→타입 불일치시 형변환 추가
class Box<T extends Fruit> {
void add(T t) {...}
}
// 컴파일
class Box {
void add(Fruit t) {...}
}
'Java' 카테고리의 다른 글
애너테이션 (0) | 2022.11.08 |
---|---|
열거형(enum) (0) | 2022.11.04 |
HashMap, TreeMap, Collections (0) | 2022.10.30 |
HashSet, TreeSet(binary search tree) (0) | 2022.10.29 |
Arrays, Comparable, Comparator (0) | 2022.10.28 |