⦁ 지네릭스(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> 제네릭 클래스. ‘TBox’ 또는 ‘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);
	}

}

출처 - 유튜브 남궁성의 정석코딩 [자바의 정석 - 기초편] 

+ Recent posts