21.01.19-40일차
👸 지네릭스(Generics)
- 컴파일시 타입을 체크해 주는 기능(compile-time type check)
- 객체의 타입 안정성을 높임, 형변환의 번거로움을 줄여줌
- 타입체크와 형변환을 생략할 수 있으므로 코드가 간결
🤴 타입변수
- 클래스를 작성할 때, Object타입 대신 타입 변수(E)를 선언해서 사용
(변수 이름은 아무거나 써도 상관없다)ex> public class ArrayList<E> extends AbstractList<E> { private transient E[] elementData; public boolean add(E o) { /* 내용 생략 */} public E get(int index) { /* 내용 생략 */} }
🤴 지네릭스 용어
Box<T> 지네릭 클래스. 'T의 Box' 또는 'T Box'라고 읽는다. T 타입 변수 또는 매개변수.(T는 타입 문자) Box 원시 타입(raw type)
🤴 지네릭 타입과 다형성
- 참조 변수와 생성자의 대입된 타입은 일치해야 한다.
ArrayList<Tv> list = new ArrayList<Tv>(); // 일치 ArrayList<Product> list = new ArrayList<Tv>(); // 불일치. 에러
- 지네릭 클래스간의 다형성은 성립 (대입된 타입은 일치해야함)
List<Tv> list = new ArrayList<Tv>(); // OK. 다형성. ArrayList가 List를 구현 List<Tv> list = new LinkedList<Tv>(); // OK. 다형성. LinkedList가 List를 구현
- 매개변수의 다형성도 성립
ArrayList<Product> list = new ArrayList<Product>(); list.add(new Product()); list.add(new Tv()); // Ok list.add(new Audio()); // Ok
🤴 제한된 지네릭 클래스
- extends로 대입할 수 있는 타입을 제한
class FruitBox<T extends Fruit>{ // Fruit의 자손만 타입으로 지정가능 ArrayList<T> list = new ArrayList<T>(); ... } - FruitBox<Apple> appleBox = new FruitBox<Apple>(); // OK FruitBox<Toy> appleBox = new FruitBox<Toy>(); // 에러. Toy는 Fruit의 자손X.
- 인터페이스인 경우에도 extends를 사용(implements 사용X)
interface Eatable{} calss FruitBox<T extends Eatable> {...}
🤴 지네릭스의 제약
- 타입 변수에 대입은 인스턴스 별로 다르게 가능
Box<Aapple> appleBox = new Box<Apple>(); // Ok. Apple객체만 저장가능 Box<Grape> appleBox = new Box<Grape>(); // Ok. Grape객체만 저장가능
- static 멤버에 타입 변수 사용불가
(static멤버는 모든 인스턴스에 공통)class Box<T> { static T item; // 에러 static int compare(T t1, T t2) {...} // 에러 }
- 배열 생성할 때 타입 변수 사용불가.
(타입 변수로 배열 선언은 가능)class Box<T>{ T[] itemArr; // Ok. T타입의 배열을 위한 참조변수 ... T[] toArray(){ T[] tmpArr = new T[itemArr.length]; // 에러. 지네릭 배열 생성불가 // new 연산자 다음에 T 쓸 수 없다. } }
🤴 와일드 카드 <?>
- 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능
<? extends T>
와일드 카드의 상한 제한. T와 그 자손들만 가능
<? super T>
와일드 카드의 하한 제한. T와 그 조상들만 가능
<?>
제한 없음. 모든 타입이 가능. <? extends Object>와 동일ex> ArrayList<? extends Product> list = new ArrayList<Tv>(); // Ok ArrayList<? extends Product> list = new ArrayList<Audio>(); // Ok ArrayList<Product> list = new ArrayList<Tv>(); // 에러. 대입된 타입 불일치
- 메서드의 매개변수에 와일드 카드를 사용
🤴 지네릭 메서드
- 지네릭 타입이 선언된 메서드(타입 변수는 메서드 내에서만 유효)
static <T> void sort(List<T> list, Comparator<? super T> c)
- 클래스의 타입 매개변수
<T>
와 메서드의 타입 매개변수<T>
는 별개class FuritBox<T>{ // 지네릭 클래스 ... static<T> voic sort(List<T> list, Comparator<? super T> c){ // 지네릭 메서드 } }
- 메서드를 호출할 때마다 타입을 대입해야함(대부분 생략 가능)
- 메서드를 호출할 때 타입을 생략하지 않을 때는 클래스 이름 생략 불가
🤴 지네릭 타입의 형변환
- 지네릭 타입과 원시 타입 간의 형변환은 바람직 하지 않다(경고 발생)
Box<Object> obj = null; Box box = (Box)objBox; // Ok. 지네릭 타입 -> 원시 타입. 경고발생 objBox = (Box<Object>)box; // OK. 원시 타입 -> 지네릭 타입. 경고발생
- 와일드 카드가 사용된 지네릭 타입으로는 형변환 가능
🤴 지네릭 타입의 제거
- 컴파일러는 지네릭 타입을 제거하고, 필요한 곳에 형변환을 넣는다.
- 지네릭 타입의 경계(bound)를 제거
- 지네릭 타입 제거 후에 타입이 불일치하면, 형변환을 추가
- 와일드 카드가 포함된 경우, 적절한 타입으로 형변환 추가
👶 출처
자바의 정석 책 & 유튜브
Author And Source
이 문제에 관하여(21.01.19-40일차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ham6482/21.01.19-40일차-xdl5iz73저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)