제네릭 기반의 클래스 정의를 통해 자료형에 의존적이지 않은 클래스 정의를 할 수 있다.
class Box<T>{
T content;
public Box(T content){
this.content = content;
}
public void show(){
System.out.println(content);
}
}
class Toy{
int price;
}
public class Main {
public static void main(String[] args){
Box<Integer> b1 = new Box<>(1);
Box<String> b2 = new Box<>("string");
Box<Toy> b3 = new Box<>(new Toy());
b1.show();
b2.show();
b3.show();
}
}
T : 타입 매개변수
Toy : 타입 인자
Box<Toy>
: 제네릭 타입(매개변수화 타입)
둘 이상의 타입 매개변수로 제네릭 클래스를 정의할 수 있다.
class Box<L,R>
과 같이 ..
타입 인자로 기본 자료형 int
등은 사용 불가능
Wrapper 클래스 Integer
를 사용해야 함
반환형 앞에 제네릭임을 표시해준다
public static <T> 반환형 함수명(매개변수,..)
와 같이 선언한다.
public static <T> Box<T> makeBox(T o);
반환형이 Box<T>
, 매개변수 T인 메소드이다.
제네릭 메소드는 메소드 호출 시 자로형이 결정된다
제네릭 메소드 호출 시
<String>makeBox("Hello");
와 같이 호출한다.
makeBox("Hello");
와 같이 제네릭 부분을 생략하고 호출하면 인자에 따라 컴파일러가 판단한다.
class Box<T extends A>
제네릭 인자 T는 A를 상속하는 클래스형만 올 수 있다.
이렇게 정의하면 T는 A클래스의 메소드를 상속하므로 Box 클래스 내에서 T를 통해 A클래스의 메소드를 사용가능하다.
interface Box<T extends A>
인터페이스에도 적용 가능
class Box<T extends A&B>
하나 이상의 클래스, 인터페이스에도 적용 가능
T는 A를 상속하고 B를 구현해야 함
제네릭 메소드에서도 가능하다.
public static <T extends A> Box<T> makeBox(T o);
와일드카드는 제네릭 메소드를 대신할 수 있는 방법이다.
<?>
를 사용해 제네릭 메소드를 선언한다.
//제네릭 메소드
public static <T> void showBox(Box<T> box);
public static <T> Box<T> createBox();
//와일드카드
public static void showBox(Box<?> box);
public static Box<?> createBox();
제네릭 메소드는 정해지지 않은 어떤 클래스형을 나타내는데 사용한다.
즉 <T>
는 Integer, Box, Box<String>
등 다양하게 나타낼 수 있다.
반면 와일드카드는 제네릭 타입, 즉 매개변수화 타입을 나타낼 때 사용해야 한다.
public static void test(? value)
위와 같이 사용할 수 없다.
public static void test(Box<?> value)
이렇게 매개변수화 타입을 나타낼 때 사용해야 한다.
public 반환형 메소드명(클래스<? extends 슈퍼클래스> 레퍼런스)
public 반환형 메소드명(클래스<? super 서브클래스> 레퍼런스)