지네릭스(Generics)
지네릭스란?
- 지네릭스는 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입체크를 해주는 기능
- 객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다
- 타입 안정성을 높인다는 것은 의도하지 않은 타입의 객체가 저장되는 것을 막고 저장된 객체를 꺼내올 때 원래의 타입과 다른 타입으로 잘못 형변환되어 발생할 수 있는 오류를 줄여준다는 뜻
- runtimeException을 컴파일 에러로 변형
지네릭 클래스의 선언
- 지네릭 타입은 클래스와 메서드에 선언 가능
- 클래스에 선언되는 지네릭 타입
- 타입 변수를 선언해서 사용
- 임의의 참조형 타입을 의미
- 객체 생성 시, 타입 변수 대신 실제 타입을 지정(대입)
public class ArrayList<T> extends abstractList<E> {
...
}
용어
class Box<T> ()
제한
- 모든 객체에 대해 동일하게 동작해야 하는 static 멤버에 타입 변수 T를 사용할 수는 없다
- T는 인스턴스 변수로 간주
- static 멤버는 인스턴스 변수를 참조할 수 없다
- 지네릭 타입의 배열을 생성하는 것도 허용되지 않는다
- 참조변수를 선언하는 것만 가능
- new 연산자는 컴파일 시점에 타입 T가 어떤 타입인지 정확히 알아야 한다
지네릭 클래스의 객체 생성과 사용
- 지네릭을 사용한 클래스가 있는 경우 이 객체를 이용해서 T타입의 객체만 저장할 수 있다
- 객체를 생성할 때는 참조변수와 생성자에 대입된 타입(매개 변수화된 타입)이 일치해야 한다
- 상속 관계여도 마찬가지다
- 객체를 추가할 때 대입된 타입과 다른 타입의 객체는 추가할 수 없다
- 하지만 상속 관계가 있을 경우 자식은 매개 변수가 될 수 있다
제한된 지네릭 클래스
- 매개변수 T에 지정할 수 있는 타입의 종류를 제한하는 방법으로는 지네릭 타입에 extends를 사용하는 것이 있다
와일드 카드
- 지네릭 타입이 다른 것만으로는 오버로딩이 성립하지 않는다
- 오버로딩은 시그니처(이름, 변수, 리턴타입)가 달라야 성립
- 지네릭 타입이 다른 두 개의 메서드는 메서드 중복 정의이다
- 이때 사용할 수 있는 것이 와일드 카드
- 와일드 카드는 어떤 타입도 될 수 있다
- extends와 super로 상한과 하한을 제한할 수 있다
<? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능
<? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능
<?> : 제한 없음. 모든 타입이 가능 <? extends Object>와 같음
지네릭 메서드
- 메서드의 선언부에 지네릭 타입이 선언된 메서드를 지네릭 메서드라 한다
- 지네릭 타입의 선언 위치는 반환 타입 바로 앞
- 지네릭 클래스에 정의된 타입 매개변수와 지네릭 메서드에 정의된 타입 매개변수는 전혀 별개의 것
- static 멤버에는 타입 매개변수를 사용할 수 없지만 메서드에 지네릭 타입을 선언하고 사용하는 것은 가능
- 메서드에 선언된 지네릭 타입은 지역 변수를 선언한 것과 같다
- 지네릭 메서드를 호출할 때 대입된 타입을 생략할 수 없는 경우에는 참조 변수나 클래스 이름을 생략할 수 없다