
변수의 선언이나 다양한 타입의 객체들을 다루는 메서드의 매개변수를 하나의 참조 자료형이 아닌 여러 자료형을 변환될 수 있도록 프로그래밍 하는 방식
컬렉션 프레임워크에서 많이 사용하고 있다.
객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어듦.
여러 참조 자료형으로 대체될 수 있는 부분을 하나의 문자로 표현한다.
이 문자를 자료형 매개변수라고 부름.
class Box<T>{ // 제네릭 타입 T를 선언
T item;
void setItem(T item) { this.item = item; }
T getItem() { return item; }
}
Box<String> b = new Box<String>(); // 타입 T 대신, 실제 타입을 지정
b.setItem(new Object()); // 에러. String 이외의 타입은 지정 불가
b.setItem("ABC"); // OK. String 타입이므로 가능.
String item = (String) b.getItem(); // 형변환 필요없음.
class Box<T> {}
/* Box<T> - 제네릭 클래스. 'T의 Box' 또는 'T Box'라고 읽음.
T - 타입 변수 또는 타입 매개변수. (T는 타입 문자)
Box - 원시타입(raw type) */
모든 객체에 동일하게 동작해야하는 static 멤버에 타입 변수 T를 사용할 수는 없다. T가 인스턴스 변수로 간주되기 때문인데, static 멤버는 인스턴스 변수를 참조할 수 없다.
제네릭 타입의 배열을 생성하는 것도 허용되지 않는다. 제네릭 배열 타입의 참조변수를 선언하는 것은 가능하지만 new T[10]과 같이 배열을 생성하는 것은 불가능하다.
제네릭 타입에 특정 종류만을 사용하도록 제한하는 것
class Box<T> { // T : Type, K : Key, V : Value, E : Element
T[] itemArr; // OK. T타입의 배열을 위한 참조변수
...
T[] toArray() {
T[] tmpArr = new T[itemArr.length]; // 에러. 제네릭 배열 생성불가
...
return tmpArr;
}
}
접근지정자 class 클래스명<T extends Fruit> {
/* extends -> 클래스/인터페이스 상관없이 항상 extends 사용.
Fruit 또는 그 하위클래스만 가능*/
// 타입 T를 사용한 코드
}
객체 생성 시 제네릭 타입을 지정하지 않으면 올 수 있는 Type 중 최상위 클래스(B)로 인식. 즉, 아래 두 코드는 동일한 의미임.
D d = new D();
D<B> d = new D<B>();
접근지정자 <T extends 최상위클래스명> T 메서드이름(T t) { // 클래스/인터페이스 상관없이 항상 extends 사용
// 부모클래스의 메서드 사용 가능
}
char charAt(int index)
- String 클래스의 메서드, String 문자열의 index 위치의 문자를 리턴
클래스명<실제 제네릭 타입> 참조 변수명 = new 클래스명<실제 제네릭 타입>();
클래스명<실제 제네릭 타입> 참조 변수명 = new 클래스명<>();
제네릭 클래스는 클래스를 정의하는 시점에 타입을 지정하는 것이 아니라 객체를 생성하는 시점에 타입을 지정함.
리턴타입 또는 매개 변수의 타입을 제네릭 타입으로 선언
제네릭 메서드의 정의 문법 구조
접근지정자<T> T 메서드이름(T t) {
// 타입 T를 사용한 코드
}
접근지정자<T, V> T 메서드이름(T t, V v) {
// 타입 T를 사용한 코드
}
접근지정자 int void 메서드이름(T t) {
// 타입 T를 사용한 코드
}
접근지정자<T> T 메서드이름(int a) {
// 타입 T를 사용한 코드
}