제네릭스(Generics)
규칙
컴파일시 타입을 체크해 주는 기능(compile-time type check) - JDK1.5
객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌.
ㄴ( 제네릭으로 특정타입만 들어올수 있도록 선언하기에, 다른타입이 들어오면 컴파일에러 확인가능)
객체를 생성시, 타입변수(E) 대신 → 실제 타입(Tv)을 지정(대입) ex. ArrayList<Tv> tvList = new ArrayList<Tv>();
참조변수와 생성자의 대입된 타입은 일치해야한다.
제네릭 클래스간의 다형성은 성립한다.(여전히 대입된 타입은 일치해야한다.)
매개변수의 다형성도 성립한다.
※ 예시
클래스 안에 Object 타입이 있는 것들은 <제네릭>을 붙여주는걸로 바뀜 ( JDK1.5 버전 이후)
ArrayList (일반클래스) → ArrayList<타입 or Object>
실행중에 에러 발생을 방지를 위한 작업
에러 발생시 실행중 에러보다는, 컴파일시 에러발생으로 유도.
왜? 중간에 실행하다가 멈추면 작업하던게 모두 날라가니까.
String str = null; → String str = "";
(안좋은예) ( 추천 )
ex) str.length()를 안좋은예로 하게되면 null로 초기화시 NullPointerException 발생.
추천예로 진행시 0 반환.
Object[] Arr = null → Object Arr = new Object[0]; or Object Arr = {};
(안좋은예) ( 추천 )
ex) arr.length()를 안좋은예로 하게되면 null로 초기화시 NullPointerException 발생
추천예로 진행시 0 반환.
ClassCastExcetion을 막기위해 <제네릭> 사용.
타입 변수
규칙
클래스를 작성할 때, Object타입 대신 → 타입 변수(E)를 선언해서 사용.
제네릭 용어
제네릭 타입과 다형성
예시
public class ex6 {
public static void main(String[] args) {
ArrayList<Product> ProductList = new ArrayList<Product>();
ArrayList<Tv> tvList = new ArrayList<Tv>();
List<Tv> tvList2 = new ArrayList<Tv>();//원시타입 다형성가능
ProductList.add(new Tv());
ProductList.add(new Audio());
tvList.add(new Tv());
tvList.add(new Tv());
printAll(ProductList);
printAll2(tvList);
}
public static void printAll(ArrayList<Product> proList) {
for(Product p : proList) {
System.out.println("Product 타입 : " + p);
}
}
public static void printAll2(ArrayList<Tv> tvList) {
for(Product p : tvList) {
System.out.println("Tv 타입 : " + p);
}
}
}
Iterator<E>
규칙
클래스를 작성할 때, Object타입 대신 T와 같은 타입 변수를 사용
class Student9{
String name = "";
int ban;
int no;
public Student9(String name, int ban, int no) {
super();
this.name = name;
this.ban = ban;
this.no = no;
}
}
public class ex6 {
public static void main(String[] args) {
ArrayList<Student9> list = new ArrayList<Student9>();
list.add(new Student9("자바왕", 1, 1));
list.add(new Student9("자바도사", 1, 2));
list.add(new Student9("홍길동", 2, 1));
Iterator<Student9> it = list.iterator();
while(it.hasNext()) {
Student9 s = it.next();
System.out.println(s.name + " " + s.ban + "반 "+ s.no+ "번");
}
}
}
HashMap<K,V>
여러 개의 타입변수가 필요한 경우, 콤마(,)를 구분자로 선언
class Student9{
String name = "";
int ban;
int no;
int kor;
int eng;
int math;
public Student9(String name, int ban, int no, int kor, int eng, int math) {
super();
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
}
}
public class ex6 {
public static void main(String[] args) {
HashMap<String,Student9> map = new HashMap<String,Student9>();
map.put("자바왕", new Student9("자바왕", 1, 1, 100, 100, 100));
Student9 s = map.get("자바왕");
System.out.println(s);
System.out.println(map);
}
}
제한된 제네릭 클래스
규칙
extends로 대입 할 수 있는 타입을 제한
interface Eatable{}
class Fruit implements Eatable{
public String toString() { return "Fruit"; }
}
class Apple extends Fruit { public String toString() { return "Apple"; }}
class Grape extends Fruit { public String toString() { return "Grape"; }}
class Toy { public String toString() { return "Toy"; }}
class ex6 {
public void main(String[] args) {
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();
FruitBox<Grape> grapeBox = new FruitBox<Grape>();
// FruitBox<Grape> grapeBox = new FruitBox<Apple>(); // 에러. 타입불일치
// FruitBox<Toy> toyBox = new FruitBox<Toy>(); // 에러. 원시타입(FruitBox)에 Toy가 없음
fruitBox.add(new Fruit());
fruitBox.add(new Apple());
fruitBox.add(new Grape());
appleBox.add(new Apple());
// appleBox.add(new Grape()); //에러. 형제간이기 때문에
grapeBox.add(new Grape());
System.out.println("fruitBox-"+fruitBox);
System.out.println("appleBox-"+appleBox);
System.out.println("grapeBox-"+grapeBox);
}
}
// 타입변수<> 에서 인터페이스는 & 기호사용
class FruitBox<T extends Fruit & Eatable> extends Box<T>{}
class Box<T> {
ArrayList<T> list = new ArrayList<T>();
void add(T item) { list.add(item); }
T get(int i) { return list.get(i); }
int size() { return list.size(); }
public String toString() { return list.toString(); }
}
제네릭의 제약
규칙
타입변수에 대입은 인스턴스 별로 다르게 가능.
static멤버에 타입변수 사용(불가) 왜? static멤버는 모든 인스턴스의 공통이니까
배열 생성할 때 타입변수 사용불가. 타입 변수로 배열 선언은 가능.
출처 : 남궁성의 정석코딩
'Java의 정석' 카테고리의 다른 글
12장. 어노테이션, 메타 어노테이션,타입 정의 및 요소 (0) | 2023.02.19 |
---|---|
12장. 제네릭 - 와일드카드, 메서드, 제네릭형변환 (0) | 2023.02.18 |
11장. 컬렉션 ( HashMap, Hashtable, Collections클래스, 정리 ) (1) | 2023.02.16 |
11장. 컬렉션 ( HashSet ) (0) | 2023.02.14 |
11장.Arrays클래스, 검색, Comparator, Comparable 정렬 (0) | 2023.02.14 |