제네릭
제네릭은 특정 타입을 지정하지 않고 사용자에 따라 타입이 지정되는 것을 말한다.
잘못된 타입이 사용되었을 때 그 문제를 컴파일 과정에서 제거할 수 있다.
class A <T>{
T type;
}
public static void main(String[] args) throws IOException {
A<Integer> i = new A<Integer>(); // int 자료형으로 변환
A<String> s = new A<String>(); // String 자료형으로 변환
}
위 코드에서 A 클래스는 어떤 형태가 들어오면 그에 따른 타입으로 변환된다.
그럴 때 제네릭에 대해 제한을 걸 수 있는데 그것이 바운디드 타입이다.
class A<T extends Number>{ // 타입을 Numaber 클래스에 있는 타입으로 제한이 가능
...
}
public static void main(String[] args) throws IOException {
A<Integer> i = new A<Integer>(); // int 자료형으로 변환이 잘 됨
A<String> s = new A<String>(); // error 발생
}
특정 클래스의 자식 클래스만을 사용할 수 있게 만들기 위해서는 extend 키워드를 사용한다.
class B<? super T>{ // T 클래스 포함 부모 클래스의 타입으로 제한이 가능하다.
...
}
특정 클래스의 부모 클래스만 인자로 받을 수 있게 하기 위해 super 키워드를 사용한다.
와일드 카드인 <?> 는 <? extends Object> 로 인식하므로 모든 타입에 대해서 전부 허용한다는 뜻이 된다.
단 </? extends T> 처럼
제네릭 메소드
class A<T>{
T type;
// static T n; error
static<T> T add(T n){
return n;
}
}
public static void main(String[] args){
System.out.println(A.get(10));
}
Static 변수는 제너릭을 사용할 수 없는데 그 이유가 A 클래스가 인스턴스화 되기 전 Static 변수가 먼저 올라가는데 이 때 변수의 타입인 T가 정해지지 않기 때문이다.
Static 메소드 자체도 같은 이유로 에러가 발생한다.
하지만 제너릭 메소드는 Static이 가능하도록 설계되어있다.
제너릭 메소드는 호출 시에 매게 타입을 지정하도록 만들었기 때문에 가능하다.
단, 제너릭 메소드의 사용되는 <\T>와 제너릭 클래스에서 사용되는 <\T>는 다른 타입이라는 것이다.
Erasure
컴파일 타임에만 타입 제약 조건을 정의하고, 런타임에서는 타입을 제거한다.
class Test<T>{
T a;
public void realTest(T test){
System.out.println(test);
}
}
위 코드가 런타임 환경에서는
class Test{
Object a;
public void realTest(Object test){
System.out.println(test);
}
}
이렇게 Object로 바뀌어 진다.
여기서 바운디드 타입으로 넘어가면
class A<T extends Number>{
T num1;
}
위 코드가
class A{
Number num1;
}
이런 식으로 상한을 가지고 런타임 떄 구동하게 되는 것이다.
'Java' 카테고리의 다른 글
| Java Study 7-3주차 (0) | 2023.11.18 |
|---|---|
| Java Study 7-1주차 (0) | 2023.11.18 |
| Java Study 6-2주차 (0) | 2023.11.11 |
| Java Study 6-1주차 (1) | 2023.11.11 |
| Java Study 5-2주차 (0) | 2023.11.05 |