컴파일시 타입을 체크해 주는 기능 - JDK 1.5
ArrayList<Animal> animalList = new ArrayList<Animal>();
animalList.add(new Animal()); // 가능
animalList.add(new Person()); // 컴파일 에러. Animal 외에 다른 타입은 불가
Animal dog = animalList.get(0); // 원래는 Object 타입을 반환하지만, 자동적으로 변환되서 변수에 들어감
객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌
꼭 정해져있는 것은 아니지만, 보통 이렇게 쓴다. 한글자일 필요도 없음.
public class ClassName<T> { ... }
public Interface InerfaceName<T> { ... }
이렇게 데이터 타입을 외부로 부터 지정할 수 있음.
이 클래스를 사용할려면, 객체를 생성할 때, 구체적인 타입을 명시해주면된다
class ClassName<E> {
private E element; // 제네릭 타입 변수
void set(E element) { // 제네릭 파라미터 메소드
this.element = element;
}
E get() { // 제네릭 타입 반환 메소드
return element;
}
}
public class Main {
public static void main(String[] args) {
ClassName<String> a = new ClassName<String>();
ClassName<Integer> b = new ClassName<Integer>();
a.set("10");
b.set(10);
}
}
여기서 알 수 있는 점은 객체를 생성할 때, 타입을 명시해주는데 Wrapper 클래스로 명시하는 것이다. 이유는 타입 파라미터로 명시할 수 있는 것은 참조 타입(Reference Type)만 올 수 있기 때문이다.
public <T> T genericMethod(T o) { // 제네릭 메소드
return o;
}
제네릭 메소드는 파라미터 타입에 따라 T 타입이 결정된다. 이런 방식이 필요하는 이유는 정적 메소드로 선언하기 위해 필요하기 때문.
static은 프로그램에 기본적으로 메모리상에 존재하는데, 이런 제네릭은 명시를 해주어야 하기에 프로그램이 모르니까 error가 뜬다. 그래서 타입을 한번 더 제네릭으로 해주는 것이다. ( 설명이 부족하다고 생각하지만, 아직까지 내가 잘 이해를 못하는 것 같다. )
제네릭에 타입을 참조 타입이면 어떤 것이든 할 수 있었는데, 만약에 특정 범위로 제한을 하고싶을 경우에 '와일드 카드'라는 것을 사용하면 된다.
키워드는 extends, super, ?(물음표)가 있다.
// 예시들..
<T extends Animal> // Animal과 Animal 자손 타입만 가능
<T super Dog> // Dog와 Dog의 부모 타입만 가능
<? extends Animal> // Animal과 Animal 자손 타입만 가능
<? super Dog> // Dog와 Dog의 부모 타입만 가능
<?> // 모든 타입 가능. <? extends Object>랑 같은 의미
: 자, 여기서 의문점이 들 것이다. T와 ?(물음표)랑 똑같은 것 같은데, 무슨 차이점이 있는가! 그것은 T는 특정 타입으로 지정이 되지만, ?(물음표)는 타입이 지정되지 않는다.
이 글은 추후에 내가 조금더 이해를 하면 언젠가 수정이 되지 않을까..