2 minute read

★Generic class : 다루는 클래스를 정해놓지 않고 사용하는 클래스, 컴파일 시에 클래스가 확정된다.

★기본적인 제네릭 클래스 선언

class Box<T> {
	T t;
	public void (T t) {
		this.t = t;
	}
	public T getT() {
		return t;
	}
}

...

public void doSomething() {
	Box<String> box = new Box<String>();
	bos.setT("헬로");
	String t = box.getT();
	//	Box안에 String이외의 다른 타입을 넣으면 컴파일 에러가 발생한다.
	//	꺼내 쓸때 캐스팅이 따로 필요없음
}

★꺽쇠<>안에 들어가는 타입을 타입 매개변수라고 한다. 컴파일시 이 타입 매개변수는 타입 소거자(Type Erasure)에 의해 삭제된다. 그래서 위의 Box<String> box = new Box<String>();는 컴파일 후에는 Box box = new Box();로 바뀐다.

★타입 파라메터 네이밍
E : 엘레멘트
K : 키
N : 숫자
T : 타입
V : 값
S,U,V… : 두번째, 세번째, 네번째 타입…

★Generic Method : 클래스 단위가 아니더라도 메소드수준에서도 사용할 수 있다.

public <U> void printBox<U info> {
	System.out.println(info)
}

함수 호출에 대헤 어떤 타입인지 선언 안해도 잘 작동한다. 컴파일러가 printBox에 String이 들어온것을 알기 때문에 U=String인것을 추론하기 때문. 이런 기능을 타입 추론(Type Inference)라 한다. 타입 추론을 통해 생성자에서도 생략이 가능하다.

Box<Integer> box = new Box<Integer>(1);
//위와 아래는 동일한 코드
Box box = new Box(1);

처럼 상속관계를 이용해 T의 범위를 제한할 수 있다. 이 경우 ClassA의 자식클래스만 T자리에 들어올 수 있다.

★Generic클래스에서 어떤 타입을 사용할지 아직 정확히 안 정해진 경우 Wildcard라는 것을 사용할 수 있다. 즉 어떤 타입이든 관계없이 해당 클래스의 메소드를 사용하고 싶을 때 ?를 타입으로 사용한다.

public int count (Set<?> s1, Set<?> s2) {
	...
}

이러한 사용법을 비 한정적 와일드카드 자료형이라고 한다.

★한정적 와일드카드 자료형 : 파라메터 클래스타입을 제한하려면 와일드카드와 extends키워드를 같이 사용한다.

  1. extends : 어떤 클래스의 서브클래스여야 한다는 의미
  2. super : 어떤 클래스의 조상클래스여야 한다는 의미

★보통 쓰기를 할 때는 extends, 읽기를 할 떄는 super를 사용하며 둘 다 할때는 wildcard를 안쓴다고한다.

★제네릭 클래스는 배열을 생성할 수 없다.

//	error code
private T[] table  = new T[10];
private Entry<K, V>[] table  = new Entry<K, V>[10];

★위 두 코드는 실행되지 않는다. 컴파일러가 컴파일을 수행할 때 type parameter인 T, K, V가 실제로 나타내는 타입을 알 수 없기 때문이다. 무슨 말이냐면 배열 생성 구문에 타입 파라메터를 써 주더라도 컴파일 타임에 타입 파라메터 정보는 사라지기 때문에 런타임에 그 정보를 사용할 수 없다. 그래서 런타임에 배열을 생성할 수 없는 것이다. 단 형변환은 가능하기 때문에 아래와 같은 트릭을 사용한다.

private T[] table = (T[])new Object[10];
private Entry<K, V>[] table  = (Entry<K, V>[])new Entry[capacity];

★첫 번째 코드는 T가 어떤 타입이든 기본적으로 Object타입이 된다. 그래서 모든 자식 클래스로 형변환이 가능하기 때문이고, 두 번째 케이스는 컴파일하면 new Entry[]의 모양이 되고 새 Entry배열속의 Entry의 Type paramenter인 K와 V는 Object타입으로 되어있다. 따라서 이를 <K, V>로 형변환 해 준 것이다. 아 말이 어렵노.

★참고로 이렇게 컴파일 타임에 타입 파라메터가 사라지는 타입을 비 구체화 타입이라고 하고, 그 반대를 구체화 타입이라고 한다.

Categories:

Updated: