관련 URL#

  1. http://www.ibm.com/developerworks/java/tutorials/j-generics/section2.html

1. 제네릭 소개#

1-1. 제네릭이란#

파라미터로 타입을 제한하는 기능
  • jdk 1.4의 Map*
Map m = new HashMap();
m.put("key", "blarg");
String s = (String) m.get("key");

  • jdk 1.5의 Map*
Map<String, String> m = new HashMap<String, String>();
m.put("key", "blarg");
String s = m.get("key");

1-2. 제네릭의 잇점#

  1. 타입 안정성(Type safety)
  2. 타입 캐스팅 코드 제거(Elimination of casts)
  3. 미세한 성능개선(Potential performance gains)

2. 제네릭 타입#

2-1. 타입 파라미터#

public interface Map<K, V> {
  public void put(K key, V value);
  public V get(K key);
}
Map<String, String> map = new HashMap<String, String>();

2-2. 타입 파라미터 명명규칙#

  1. 대문자
  2. 한개의 알파벳
  3. JDK 에서 추천되는 형태
    • K - A key, such as the key to a map
    • V - A value, such as the contents of a List, Set, or the values in a Map
    • E - An exception class
    • T - A generic type

2-3. 제네릭 타입은 상속의 개념을 적용하지 못한다. #

Object 는 String 의 상위타입이지만 List<Object> 는 List<String>의 상위타입이 되지 못한다. 코드로 설명해보면
Integer[] intArray = new Integer[10];  
Number[] numberArray = intArray;
이와 같은 형태의 코드는 문제없이 잘 작동하나, 아래와 같은 형태는 에러를 발생시킨다.
List<Integer> intList = new ArrayList<Integer>();
List<Number> numberList = intList; // invalid

2-4. 타입 와일드카드#

앞서 설명한 것처럼 List<Object> 는 List<Integer>의 상위타입이 아니기 때문에 아래처럼 코드를 작성할 경우 printList(list) 부분에 컴파일 에러가 발생한다.
public static void main(String[] args) {
	List<Integer> list = new ArrayList<Integer>();
	list.add(new Integer(1));
	
	printList(list);
}

public static void printList(List<Object> list){
	for (Object o : list){
		System.out.println(o);
	}
}
The method printList(List<Object>) in the type Test is not applicable for the arguments (List<Integer>)

이러한 경우에는 printList 메서드를 작성함에 있어 제네릭으로 어떠한 타입도 들어갈 수 있다는 정의를 해줘야 하는데, 이 때 사용하는 것이 타입 와일드카드(? 로 표기)이다.

public static void printList(List<?> list){
	for (Object o : list){
		System.out.println(o);
	}
}

타입와일드카드를 사용한 경우 아래와 같은 처리도 가능하게 된다.

List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(42));
List<?> lu = li;
System.out.println(lu.get(0));

위 처럼 처리가능하다하더라도 lu 인스턴스에 대해서는 Integer 라는 타입에 충분히 처리할 수 는 없기 때문에 Integer 타입으로 추가는 불가능하다.

List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(42));
List<?> lu = li;
lu.add(new Integer(43));  // error

2-5. 제네릭 메서드#

public <T> T ifThenElse(boolean b, T first, T second) {
  return b ? first : second;
}

String s = ifThenElse(b, "a", "b");					// first 파라미터의 타입이 String타입, second 파라미터 타입이 String타입
Integer i = ifThenElse(b, new Integer(1), new Integer(2));		// first 파라미터의 타입이 Integer타입, second 파라미터 타입이 Integer타입
String s = ifThenElse(b, "pi", new Float(3.14));			// first 파라미터의 타입이 String타입, second 파라미터 타입이 Float타입, 이 경우에는 에러가 발생함

2-6. 제한된 타입#

앞서 본 제네릭 메서드에서는 명시할 타입에 대해 제한하지 않는다. 타입을 Number 타입으로 제한하고자 하는 요구사항이 있다면 제한할 수 있다.
public class Matrix<V extends Number> { ... }

Matrix<Integer>, Matrix<Float> 로 사용하면 문제가 없지만, Matrix<String> 로 사용하면 에러가 발생하게 된다.

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-6) was last changed on 11-Oct-2010 19:02 by DongGukLee  
G’day (anonymous guest) My Prefs

Referenced by
OpenSources

JSPWiki v2.8.4