제네릭(Generic)이란 결정되지 않은 타입을 파라미터로 처리하고 실제 사용할 때 파라미터를 구체적인 타입으로 대체시키는 기능
public class Box<T, K> {
public T content;
private K model;
// Getter의 매개변수와, Setter의 리턴 타입 역시 타입 파라미터로 선언해야함.
public T getContent() { return this.kind; }
public void setModel(M model) { this.model = model; }
}
Box<String> box = new Box<String>();
Box<String> box = new Box<>(); // 생략도 가능
box.content = "Hi";
String content = box.content;
Box<Integer> box = new Box<Integer>();
box.content = 100;
int content = box.content;
이때 사용된 T는 타입 파라미터로 불림.
=> Ex. Box<int>가 될 수 없는 이유는 기본 타입은 타입 파라미터의 대체 타입이 될 수 없기 때문이다. Integer은 클래스이므로 가능
제네릭 타입은 결정되지 않은 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.
제네릭 타입은 선언부에 '<>' 부호가 붙고 그 사이에 타입 파라미터들이 위치한다.
public class 클래스명<A,B,...> {...}
public interface 인터페이스명<A,B, ...> {...}
외부에서 제네릭 타입을 사용하려면 타입 파라미터에 구체적인 타입을 지정해야 한다.
만약 지정하지 않으면 암묵적으로 모든 클래스의 최상위 부모 클래스인 Object 타입으로 지정이 됨. 따라서 모든 객체는 부모 타입인 Object 클래스로 자동 타입 변환됨.
제네릭 메소드는 타입 파라미터를 가지고 있는 메소드를 말한다.
타입 파라미터가 메소드 선언부에 정의된다는 점에서 제네릭 타입과 차이점이 있다.
리턴 타입 앞에 <> 기호를 추가하고 타입 파라미터를 정의한 뒤, 리턴 타입과 매개변수 타입에서 사용한다.
public <A,B, ...(타입 파라미터)> 리턴 타입 메소드명(매개변수, ...) { ... }
=> public <T> Box<T> boxing(T t) { ... }
=> boxing() 메소드는 타입 파라미터로 <T>를 정의하고 매개변수 타입과 리턴 타입에서 T를 사용한다. 리턴 타입은 T를 내용물로 갖는 Box 객체이다.
타입 파라미터 T는 매개값이 어떤 타입이냐에 따라 컴파일 과정에서 구체적인 타입으로 대체된다.
경우에 따라 타입 파라미터를 대체하는 구체적 타입을 제한할 필요가 있다. 예를 들어 숫자 연산 제네릭 메소드는 대체타입으로 Number 또는 자식 클래스(Byte, Short, Integer, Long, Double)로 제한할 필요가 있다.
public <T extends 상위타입> 리턴타입 메소드(매개변수, ...) {...}
상위 타입으로 클래스 뿐만 아니라 인터페이스도 가능하다. 그러나 implements를 사용하진 않는다.
제네릭 타입을 매개값이나 리턴 타입으로 사용할 때 타입 파라미터로 ?(와일드카드)를 사용할 수 있다.
?는 범위에 있느 모든 타입으로 대체할 수 있다는 표시이다.
예를 들어 다음과 같은 상속 관계가 있다고 가정해보자.
타입 파라미터의 대체 타입으로 Student와 자식 클래스인 HighStudent와 MiddleStudent만 가능하도록 매개변수를 다음과 같이 선언할 수 있다.
리턴타입 메소드명(제네릭타입<? extends Student> 변수) {...}
반대로 Worker와 부모클래스인 Person만 가능하도록 매개변수를 다음과 같이 선언할 수 있다.
리턴타입 메소드명(제네릭타입<? super Worker> 변수) {...}
참조:
이것이 자바다 교육 현장에서 가장 많이 쓰이는 JAVA 프로그래밍의 기본서 [ 개정판 ] - 신용권, 임경균 저 | 한빛미디어