⦁ 지네릭스(Generics)란?
- 컴파일시 타입을 체크해 주는 기능(compile-time type check)
- 객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌
ArrayList<Tv> tvList = new ArrayList<Tv>(); // Tv객체만 저장할 수 있는 ArrayList를 생성
tvList.add(new Tv()); // OK
tvList.add(new Audio()); // 컴파일 에러, Tv 외에 다른 타입은 저장 불가
지네릭스의 장점)
1. 타입 안정성을 제공한다.
2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다.
=> ClassCastException(형변환에러)을 Compile time에러로 끌어옴.
프로그램을 실행하기 전 컴파일 단계에서 형변환에러를 잡을 수 있게 함.
ex)
import java.util.ArrayList;
public class GenericTest {
public static void main(String[] args) {
// ArrayList list = new ArrayList(); // JDK1.5이전. 지네릭스 도입 이전
ArrayList<Integer> list = new ArrayList<Integer>(); // JDK1.5 이후
list.add(10);
list.add(20);
// list.add("30"); // 타입 체크가 강화됨. 지네릭스 덕분에
Integer i = list.get(1); // 따로 형변환 해주지 않아도 됨
System.out.println(list);
}
}
⦁ 타입 변수
- 클래스를 작성할 때, Object타입 대신 타입 변수(E)를 선언해서 사용.
public class ArrayList extends AbstractList { // 일부 생략
private transient E[] elementData;
public boolean add(E o) { /* 내용생략 */ }
public E get(int index) { /* 내용생략 */ }
...
}
- 객체를 생성시, 타입 변수(E) 대신 실제 타입(Tv)을 지정(대입)
ArrayList<Tv> tvList = new ArrayList<Tv>();
- 타입 변수 대신 실제 타입이 지정되면, 형변환 생략가능
ArrayList<Tv> tvList = new ArrayList<Tv>();
tvList.add(new Tv());
Tv t = tvList.get(0); // 형변환 불필요
⦁ 지네릭스 용어
Box<T> 제네릭 클래스. ‘T의 Box’ 또는 ‘T Box’라고 읽는다.
T 타입 변수 또는 타입 매개변수. (T는 타입 문자)
Box 원시 타입(raw type)
- 참조 변수와 생성자의 대입된 타입은 일치해야 한다.
ArrayList<Tv> list = new ArrayList<Tv>(); // OK. 일치
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.
ex)
import java.util.*;
class Product{}
class Tv extends Product {}
class Audio extends Product {}
public class Ex12_1 {
public static void main(String[] args) {
ArrayList<Product> productList = new ArrayList<Product>();
ArrayList<Tv> tvList = new ArrayList<Tv>();
// ArrayList<Product> tvList = new ArrayList<Tv>(); // 에러.
// List<Tv> tvList = new ArrayList<Tv>(); // OK. 다형성
productList.add(new Tv());
productList.add(new Audio());
tvList.add(new Tv());
tvList.add(new Tv());
// tvList.add(new Audio()); // 에러, Tv 또는 Tv의 자손이 들어갈 수 있음.
printAll(productList);
// printAll(tvList); // 컴파일 에러가 발생한다.
}
public static void printAll(ArrayList<Product> list) {
for (Product p : list)
System.out.println(p);
}
}
⦁ Iterator<E>
- 클래스를 작성할 때, Object타입 대신 T와 같은 타입 변수를 사용
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
ex)
import java.util.*;
class Student {
String name = "";
int ban;
int no;
Student(String name, int ban, int no) {
this.name = name;
this.ban = ban;
this.no = no;
}
}
public class Ex12_2 {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("자바왕", 1, 1));
list.add(new Student("자바짱", 1, 2));
list.add(new Student("홍길동", 2, 1));
Iterator<Student> it = list.iterator();
while (it.hasNext()) {
// Student s = (Student)it.next(); // 지네릭스를 사용하지 않으면 형변환 필요.
// Student s = it.next();
// System.out.println(s.name);
System.out.println(it.next().name);
}
}
}
⦁ HashMap<K,V>
- 여러 개의 타입 변수가 필요한 경우, 콤마(,)를 구분자로 선언
HashMap<String, Student> map = new HashMap<String, Student>(); // 생성
map.put("자바왕", new Student("자바왕",1,1,100,100,100)); // 데이터 저장
HashMap 클래스 중 일부)
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) { /* 내용 생략 */ }
...
}
ex)
import java.util.*;
class Student {
String name = "";
int ban;
int no;
int kor;
int eng;
int math;
Student(String name, int ban, int no, int kor, int eng, int math) {
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
}
}
public class Practice {
public static void main(String[] args) {
HashMap<String, Student> map = new HashMap<>(); // JDK1.7부터 생성자에 타입지정 생략가능
map.put("자바왕", new Student("자바왕", 1, 1, 100, 100, 100));
// public Student get(Object key)
Student s = map.get("자바왕");
System.out.println(s.name);
}
}
출처 - 유튜브 남궁성의 정석코딩 [자바의 정석 - 기초편]
'Java > Java의 정석' 카테고리의 다른 글
220325 Java - Chapter.12 지네릭스, 열거형, 애너테이션 Part.3 (0) | 2022.03.25 |
---|---|
220324 Java - Chapter 12. 지네릭스, 열거형, 애너테이션 Part.2 (0) | 2022.03.24 |
220322 Java - Chapter.11 Collections Framework Part.3 (0) | 2022.03.23 |
220321 Java - Chapter.11 Collections Framework Part.2 (0) | 2022.03.21 |
220319 Java - Chapter 11. Collections Framework Part.1 (0) | 2022.03.19 |