Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 해시
- 소프티어
- JavaScript
- programmers
- Programming
- Java
- Computer Science
- 관계형 데이터베이스
- BFS
- 프로그래머스
- Python
- 티스토리챌린지
- Steve Jobs
- softeer
- thinking differently
- nextInt
- SQL
- java.lang 패키지
- StringTokenizer
- 알고리즘
- 백준
- 반복문
- Spring Framework
- MySQL
- Java script
- 오블완
- 자바의 정석(기초편)
- 코딩테스트
- Spring
- 영어원서
Archives
- Today
- Total
도라에몽 개발자
지네릭스(Generics) 본문
- 정의
- 컴파일 시 타입을 체크해주는 기능을 의미함. (compile-time type check)
- 미리 저장할 객체의 타입을 지정하여 알려줌으로서, 다른 타입의 객체는 저장하지 못하도록 함.
Ex. ClassCastException (형변환 에러)과 같은 RuntimeException의 발생 방지하여 Runtime error (실행 중 발생하는 오류) 발생하기 전, compile time error (컴파일 시 발생하는 오류) 발생시켜 미리 수정할 수 있도록 함.
(∵ Runtime error 발생시 프로그램 죽어서 이슈가 훨씬 큰 편...) - 특징
- 객체의 타입 안정성을 높이고, 형변환의 번거로움을 줄여줌.
→ 형변환 생략 가능하여 코드가 간결해지는 장점 있음.
// TV 객체만 저장할 수 있는 ArrayList 생성
ArrayList<Tv> tvList = new ArrayList<Tv>;
tvList.add(new Tv());
tvList.add(new Audio()); // 컴파일 에러 발생함. Tv 객체 외에 다른 타입은 저장 불가함.
타입 변수
- 정의
- 클래스를 작성할 때, Object 타입 대신에 '타입 변수(E)'를 선언하여 사용하는 것
- '타입 변수'는 보통 Type의 T 또는 Element의 E를 사용하기도 하나, 어떤 알파벳을 쓰든 상관은 없음. - 타입 변수에 '대입'하는 방법
- 객체 생성 시, 타입 변수(E) 대신 실제 타입(Tv)을 지정(=대입)해줌.
- 타입 변수 대신 실제 타입이 지정되면, 형변환 생성 생략 가능하다는 장점이 있음.
지네릭스(Generics) 용어
- Box<T>
- 지네릭 클래스로, 'T의 Box' 또는 'T Box'라고 읽음. - T
- 타입 변수 또는 타입 매개변수라고 함. - Box
- 원시 타입 (raw type)
지네릭 타입과 다형성
- 주의사항
- 참조 변수와 생성자의 대입된 타입은 일치해야 함.
→ 조상과 자손의 관계이더라도, 참조 변수와 생성자의 대입된 타입은 일치해야 함.
- 지네릭 클래스간의 다형성은 성립되며, 대입된 타입 자체는 일치해야 함.
- 매개 변수의 다형성은 성립됨.
ArrayList<Product> list = new ArrayList<Product>();
ArrayList<Product> list = new ArrayList<Tv>(); // 타입 불일치 시 error 발생
List<Tv> list = new LinkedList<Tv>(); // 클래스 타입 간의 다형성 적용 가능
list.add(new Product());
// Product의 자손객체인 Tv, Audio 저장
list.add(new Tv()); // Product의 자손인 Tv 객체 저장
list.add(new Audio()); // Product의 자손인 Audio 객체 저장
// 대신 ArrayList에 저장된 Tv, Audio 객체를 꺼낼 때는, 형변환 시행 필요함.
Product p = list.get(0); // 형변환 불필요
Tv t = (Tv)list.get(1) // 형변환 시행
Audio a = (Audio)list.get(2); // 형변환 시행
지네릭스(Generics) 클래스의 종류
- Iterator<E>
- 클래스를 작성할 때, Object 타입 대신 T와 같은 타입 변수를 사용함. - HashMap<K,V>
- 여러 개의 타입 변수가 필요한 경우에는 콤마(,)를 구분자로 선언함.
제한된 지네릭 클래스
- 정의
- extends로 대입할 수 있는 타입을 제한함.
→ 특정 타입의 '자손들' 대입할 수 있도록 제한 가능함.
- 인터페이스인 경우에도 extends를 활용함. (cf. 원래 인터페이스는 implements를 사용함.)
cf. 클래스 A의 자손이면서, 동시에 B 인터페이스도 함께 구현해야 하는 경우에는 '&' 기호를 사용하여 연결함.
→ class FruitBox<T extends A & B> { ... } - 지네릭스의 제약
1) 타입 변수에 대입은 인스턴스 별로 다르게 가능함.
2) static 멤버에는 타입 변수 사용 불가함.
3) 배열 생성 시 타입 변수 사용 불가하나, 타입 변수로 배열 선언은 가능함.
// 여러 개의 객체별 다른 타입 지정 가능
Box<Apple> appleBox = new Box<Apple>();
Box<Grape> grapeBox = new Box<Grape>();
// static 멤버에 타입 변수 T 사용 불가함.
static T item; // error
// 지네릭 배열 타입 참조변수 선언은 가능하나, 지네릭 배열 생성은 불가함.
T[] itemArr; // T타입 배열을 위한 참조변수 itemArr 선언은 가능함.
T[] temArr = new T[itemArr.length]; // error - 지네릭 배열, 객체 생성 불가능함. (new T... 불가)
와일드 카드
- 정의
- 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능함. (*타입이 달라도 허용되도록 하는 필살기라고 생각하면 될 듯) - 종류
<? extends T>
- 와일드 카드의 상한 제한, T와 그 자손들만 가능함.
<? super T>
- 와일드 카드의 하한 제한, T와 그 조상들만 가능함.
<?>
- 제한 없이, 모든 타입에 가능함. <? extends Object>와 동일하다고 보면 됨.
지네릭 메서드
- 정의
- 지네릭 타입이 선언된 메서드로, 타입 변수는 메서드 내에서만 유효함.
- 클래스의 타입 매개변수<T>와 메서드 타입 매개변수<T>는 별개임.
- 메서드를 호출할 때마다 다른 지네릭 타입을 대입할 수 있음. (대부분 생략 가능)
→ 보통 와일드 타입 사용 불가할 때 지네릭 메서드를 사용하는 경우가 많음.
- 메서드를 호출할 때 타입을 생략하지 않는 경우에는 클래스 이름 생략 불가함.
지네릭 타입의 형변환
- 정의 및 활용
- 지네릭 타입과 원시 타입 간의 (타입 간의)형변환은 가능은 하지만, 바람직하지 않음. (*경고 발생)
▶ 오류 발생을 줄이기 위해, 참조 변수의 객체 타입과 생성자의 객체 타입 모두 생략하지 않고 작성하는 것을 권장함.
- 와일드 카드가 사용된 지네릭 타입으로는 형변환 가능함.
Box box = null;
Box<Object> objBox = null;
// 타입 간의 형변환 - 가능, 경고
box = (Box)objBox; // 지네릭 타입을 원시 타입으로 형변환; 경고 발생
objBox = (Box<Object>)box; // 원시 타입을 지네릭 타입으로 형변환; 경고 발생
Box<Object> objBox = null;
Box<String> strBox = null;
// 대입된 타입이 다른 지네릭 타입 간의 형변환 - 불가능, 에러
objBox = (Box<Object>)strBox; // Box<String>을 Box<Object>로 형변환; error
strBox = (Box<String>)objBox; // Box<Object>를 Box<String>로 형변환; error
지네릭 타입의 제거
- 정의 및 활용
- 컴파일러는 지네릭 타입을 제거하고, 필요한 곳에 형변환을 넣음.
① 지네릭 타입의 경계(bound)를 제거함.
② 지네릭 타입 제거 후에 타입이 불일치하면 형변환 추가함.
③ 와일드 카드가 포함된 경우, 적절한 타입으로 형변환 추가함.
/* 지네릭 타입 경계 제거 */
class Box<T extends Fruit> { // Box의 타입은 Fruit의 자손과 같다는 의미
void add(T t) { ... }
}
// 위와 같은 코드를 아래와 같이 수정할 수 있음.
class Box { // 지네릭 타입 선언(<T extends Fruit>) 제거
void add(Fruit t) { ... } // T는 Fruit으로 치환됨.
}
'LANGUAGE > Java' 카테고리의 다른 글
애너테이션(Annotations) (0) | 2023.11.29 |
---|---|
열거형(enum) (1) | 2023.11.29 |
Stream API (1) | 2023.11.28 |
Collections Framework (컬렉션 프레임웍) - Collections (0) | 2023.11.28 |
Collections Framework (컬렉션 프레임웍) - HashMap, Hashtable (1) | 2023.11.28 |