지네릭스(Generics) 란?
1. 컴파일시 타입을 체크해 주는 기능(compile-time type check) - JDK1.5
// TV 객체만 저장할 수 있는 ArrayList를 생성
ArrayList<Tv> tvList = new ArrayList<Tv>();
tvList.add(new Tv());
tvList.add(new Audio()); // 컴파일 에러! Tv 외에 다른 타입은 저장불가
}
2. 객체의 타입 안전성을 높이고 형변환의 번거로움을 줄여줌.
ArrayList tvList = new ArrayList();
tvList.add(new Tv());
Tv tv = (Tv) tvList.get(0); // Object 타입 변환(형변환 필요)
↓
ArrayList<Tv> tvList = new ArrayList<Tv>();
tvList.add(new Tv());
Tv tv = tvList.get(0); // 형변환 불필요, 컴파일러가 자동형변환
지네릭스 장점
- 타입 안전성을 제공한다.(ClassCastException 형변환 에러)
- 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다.
ArrayList는 Object를 매개변수로 받을 수 있기 때문에 모든 종류의 객체를 인수로 받을 수 있었다.
하지만 지네릭스가 도입된 후 타입을 지정한 후 잘못 들어왔을 시에 컴파일 오류를 내주고 있다.
이는 "실행시 발생에러를 어떻게 컴파일러로 끌어올까? "하는 고민 끝에 나온 결과물이다.
ArrayList list = new ArrayList();
list.add(10);
list.add(20);
list.add("30");
Integer i = (Integer)list.get(2); // 형변환 에러, 런타임 오류
System.out.println(i);
↓
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add(20);
list.add("30"); // 컴파일 오류, 지네릭스 덕분에 타입 체크가 강화됨
Integer i = (Integer)list.get(2); // 형변환 에러, 런타임 오류
System.out.println(i);
타입 변수
지네릭 클래스를 작성할 떄, Object 타입 대신 타입 변수(E)를 선언해서 사용.
타입 변수에 대입하기
- 객체를 생성시, 타입변수(E) 대신 실제 타입(Tv)를 대입
- 타입 변수 대신 실제 타입이 지정되면, 형변환 생략가능!
// 타입 변수 E 대신에 실제 타입 Tv를 대입
ArrayList<Tv> tvList = new ArrayList<Tv>();
지네릭스 용어
Box<String> b = new Box<String>();
Box<T>: 지네릭 클래스, 'T의 Box' 또는 'T Box'라고 읽는다.
T: 타입 변수 또는 타입 매개변수.(T는 타입 문자)
Box: 원시 타입(raw type)
지네릭 타입과 다형성
참조 변수와 생성자이 대입된 타입은 일치해야 한다.
class Product{ }
class Tv extends Product{ }
class Audio extends Product{ }
ArrayList<Tv> tvList = new ArrayList<Tv>(); // OK. 일치
ArrayList<Product> tvList = new ArrayList<Tv>(); // 에러. 불일치
지네릭 클래스 간의 다형성은 성립(여전히 대입된 타입은 일치해야 한다)
List<Tv> list = new ArrayList<Tv>();
List<Tv> list = new LinkedList<Tv>();
매개변수의 다형성도 성립
ArrayList<Product> List = new ArrayList<Product>();
list.add(new Product());
list.add(new Tv()); // OK, Product의 자손
list.add(new Audio()); // OK, Product의 자손
boolean add(E e){...} // 기존
boolean add(Product e){...} // 변경 후, 자손 객체 쌉가능
Product p = list.get(0);
Tv t = (Tv)list.get(1); // list.get의 반환타입이 Product로 바뀌었기 떄문에 Tv 타입으로 받아야 한다.
public class Ex3 {
public static void main(String[] args) {
ArrayList<Product> productList = new ArrayList<Product>();
ArrayList<Tv> tvList = new ArrayList<Tv>();
//ArrayList<Product> tvList1 = new ArrayList<Tv>(); // 에러.
//List<Tv> tvList2 = new ArrayList<Tv>(); // OK. 다형성
productList.add(new Tv()); // public boolean add(Product e){... }
productList.add(new Audio()); // public boolean add(Product e){... }
tvList.add(new Tv());
tvList.add(new Tv());
printAll(productList);
//printAll(tvList); // 컴파일 에러가 발생한다.
printAll2(tvList);
}
public static void printAll(ArrayList<Product> list) {
for (Product p : list) {
System.out.println(p);
}
}
public static void printAll2(ArrayList<Tv> list) {
for (Tv t : list) {
System.out.println(t);
}
}
}
class Product{ }
class Tv extends Product{ }
class Audio extends Product{ }
ex.generics.Tv@1d81eb93
ex.generics.Audio@7291c18f
ex.generics.Tv@34a245ab
ex.generics.Tv@7cc355be
'Java' 카테고리의 다른 글
[Java] 지네릭 클래스의 제약 (0) | 2024.05.10 |
---|---|
[Java] Iterator<E>, Map<K, V> (0) | 2024.05.09 |
[Java] Collections 컬렉션을 위한 메서드 (0) | 2024.05.08 |
[Java] HashMap 키와 값 (0) | 2024.05.08 |
[Java] TreeSet 범위 탐색, 정렬 (0) | 2024.05.08 |