Generics
다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크(Compile-Time Type Check)를 해주는 기능.
인스턴스 별로 다르게 동작하도록 하려고 만든 기능.
다룰 객체의 타입을 미리 명시해줌으로써 번거로운 형변환을 줄여준다.
지네릭스를 모르고는 Java API 문서조차 제대로 보기 어려울 만큼 중요하다.
장점
타입 안전성 제공
타입 체크와 형변환을 생략할 수 있어 코드가 간결해 진다.
지네릭 클래스의 객체 생성
참조 변수와 생성자에 타입 T 대신에 사용될 실제 타입을 지정한다.
어떤 타입이든 한 가지 타입을 정해서 담을 수 있다.
생성자의 타입은 참조 변수의 타입으로 추정 가능할 경우 생략할 수 있다. (JDK1.7부터)
참조 변수와 생성자에 대입된 타입이 일치해야 한다.
두 타입이 상속 관계에 있더라도 대입된 타입이 다르다고 간주된다.
두 지네릭 클래스의 타입이 상속관계에 있고, 대입된 타입이 같으면 괜찮다.
타입을 지정하지 않을 경우, 지네릭 타입을 지정하지 않아서 안전하지 않다는 경고가 발생한다.
용어
Test<String> test = new Test<String>();
Test<대입된 타입> test = new Test<String>();
지네릭 타입 호출 test = new 지네릭 타입 호출();
Test<String> |
지네릭 타입 호출. 타입 매개변수에 타입을 지정하는 것 |
String |
대입된 타입. 매개변수화된 타입 Parameterized Type. 타입 매개변수에 지정된 타입 |
지네릭 클래스의 사용
Test<T>의 객체에 setItem(T item)으로 객체를 추가할 때, 대입된 타입과 다른 타입의 객체는 추가할 수 없다.
타입 T가 Animal인 경우, Animal의 자손들은 매개변수가 될 수 있다.
제한된 지네릭 클래스
타입 매개변수 T에 저장할 수 있는 타입의 종류를 제한한다.
특정 타입의 자손들만 대입할 수 있게 할 경우 → 지네릭 타입에 와일드 카드의 상한 제한 'extends'를 사용한다.
인터페이스를 구현해야 한다는 제약이 필요한 경우 → 'implements'가 아닌 'extends'를 사용한다.
특정 타입의 자손이면서 인터페이스도 구현해야 할 경우 → '&' 기호로 연결한다.
지네릭 메서드
메서드의 선언부에 지네릭 타입이 선언된 메서드.
반환 타입 바로 앞에 지네릭 타입을 선언한다.
메서드에 선언된 지네릭 타입은 지역 변수를 선언한 것과 같다.
!! 지네릭 클래스에 정의된 타입 매개변수와 지네릭 메서드에 정의된 타입 매개변수는 전혀 별개의 것이다.
→ 지네릭 클래스가 아닌 클래스에도 정의될 수 있다.
→ 메서드가 static이건 아니건 상관 없다.
→ 내부 클래스에 선언된 타입 문자가 외부 클래스의 타입 문자와 같아도 구별된다.
이전 글에 나왔던 makeJuice()를 지네릭 메서드로 바꾸면 다음과 같다.
매개변수의 타입이 복잡할 때 유용하다. → 타입을 별도로 선언.
Example 복잡하게 선언된 지네릭 메서드
타입 T를 요소로 하는 List를 매개변수로 허용.
'T'는 Comparable을 구현한 클래스여야 한다. (<T extends Comparable>)
'T' 또는 그 조상의 타입을 비교하는 Comparable이어야 한다. (Comparable<? super T>)
참고 서적: 자바의 정석 3판 2