Genericby Seㅈoong

Generic 알아보기!

제네릭(Generic)

  • java 1.5(5.0) 부터 추가된 문법으로, 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법이다.
    주로 컬렉션 클래스 컴파일 타임에 자료형의 안정성을 보장하기 위해 사용한다.

제너릭 클래스

  • 특징
    1. 클래스 선언에 형식 타입 파라미터(Formal Type Parameter)가 포함된 클래스
    2. 클래스 사용시 타입정보를 인자로 전달 받는다는 의미로 매개변수화된 타입(parameterized type)라고 부르기도 한다. 같은 맥락으로 일반 클래스는 원천타입(Raw type)라고 부른다.
    3. 실제 타입(Actual Type)정보는 해당 클래스타입의 레퍼런스변수 선언 및 인스턴스 생성시에 제공된다.
  • 제네릭 클래스의 예: ArrayList
    public class ArrayList extends AbstractList`` implements List``, RandomAccess, Cloneable, java.io.Serializable{
    public boolean add(E e)
    ensureCapacityInternal(size + 1); // Increments modCount!!
    elementData[size++] = e;
    return true;
    }
    }
    • E: Element / K-V: Key-Value / N: Number / T: 일반적인 제네릭 타입
  • 제네릭 클래스 생성:
    제네릭 클래스 선언, 생성시 모두 실제 타입(Actual Type)을 넘겨줘야 한다.
    List<String> list = new ArrayList<String>()

제네릭 메소드

  1. 메소드 선언에 형식 타입 파라미터(Formal Type Parameter)가 포함된 메소드
  2. 클래스 범위가 아닌 특정 메소드에 대해서만 제네릭 사용이 가능하다.
  3. 클래스 제네릭과는 다르게 형식타입 식별자가 반환타입 앞에 명시된다.
  • 제네릭 메소드의 예:
    public <T> void genericMethod(T formalType){ System.out.println(formalType); }

  • 제네릭 메소드 호출:
    실제타입을 명시 해야하나 생략시 메소드 호출시 전달되는 매개변수의 자료형으로 실제타입이 정해진다.

    1. String str = new String("actualTypeIsString"); clazz.<String>genericMethod(str);
    2. clazz.genericMethod(str) - str이 String이기 때문에 실제타입은 String이 된다.

와일드 카드 <?>

  1. 형식 타입 파라미터에 와일드 카드 ?를 사용하면 모든 실제타입사용가능
  2. 실제타입의 제네릭 인스턴스 뿐만 아니라 실제타입과 상속관계에 있는 타입의 제네릭 인스턴스를 참조할 수 있다.
  3. ? extends Parent: Parent를 상속하는 실제 타입
  4. ? super Child: Child가 상속하는 실제 타입
  5. 참고 자료: 와일드 카드가 필요한 이유

제네릭 상속

  1. 상위 클래스의 형식 타입 유지 상속: Child는 제네릭 클래스를 유지
    class Child<T> extends parent<T>
  2. 상위 클래스의 실제 타입을 지정해 상속: Child는 String을 실제타입으로 갖는다.
    class Child extends parent<String>

특징

  1. 클래스 제네릭의 형식 타입 파라미터는 static(변수, 메소드, 블럭)에서 사용할 수 없다. 제네릭 클래스의 형식 타입의 실제 타입은 외부에서 제네릭 클래스 타입을 선언하거나 생성할 때 결정되기 때문에 클래스가 메모리에 올라갈때 이미 실행되는 static문에서는 실제타입을 알 수 없다.
  2. 런타임에 형식 타입 파라미터 검사가 불가능하다. 제네릭타입은 컴파일 타임에만 유효하고 런타임에는 존재하지 않는다.
    컴파일 오류:
    ArrayList<String> list = new ArrayList<String>(); if(list instanceof ArrayList<String>){ return "같은 타입" }
  3. 둘 이상의 형식 타입 파라미터를 사용할 수 있다.
    public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ...
  4. 참조 데이터 타입만 허용한다.
  5. 형식 타입 파라미터를 특정 클래스를 상속하거나 상속받은 클래스로 제한할 수 있다.(extends, super)
    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { ...
  6. 제네릭 클래스내에서 형식 타입으로 인스턴스 생성시 컴파일 애러가 발생한다.

더 알고싶다.

제네릭 메소드에서 와일드 카드 사용시 리턴타입 앞에 형식 타입을 명시하는것과 파라메터에 명시하는것의 차이에 대해서 더 알아봐야겠다.

Published 01 March 2015