[Java] Generic , Wild Card 정리
Generic이란?
ArrayList<String>
처럼 받는 타입을 제한하는 것입니다.
사용하는 이유
각 타입별로 똑같은 코드를 짜지 않아도 되기 때문입니다.
예를 들어 이전의 ArrayList는 Object타입을 활용하여 만들어졌었고, 따라서 get할때 Casting이 필요했었습니다.
또한, Compile 단계에서 에러를 발생시켜 신뢰성있는 프로그램이 되도록 합니다.
차이점
기존의 방식
ArrayList files = new ArrayList();
// get 하는 경우 Casting이 필요합니다
String filename = (String)files.get(0);
// String만 받기를 원하지만 다른 타입들도 add가 가능합니다
files.add(new File("Some Path"));
Generic
ArrayList<String> files = new ArrayList<>();
//따로 Casting이 필요 없습니다.
String filename = files.get(0);
//Compile Error가 발생하여 잘못됨을 Compile단계에서 알려줍니다.
files.add(new File("Some Path"));
Generic Class
pyblic class Pair<T>{ // T는 Type variable이라고 불립니다.
private T first;
private T second;
public Pair(){
first = null;
second = null;
}
public T getFirst(){
return first;
}
public T getSecond(){
return second;
}
public void setFirst(T first){
this.first = first;
}
public void setSecond(T second){
this.second = second;
}
}
Pair라는 클래스가 위와 같이 정의되어있다면, Pair<String> pair = new Pair();처럼 인스턴스화 하게될때 Pair안의 T들은 모두 String으로 대치되게 됩니다.
public class Pair<T,U> {
T first;
U second;
}
위 처럼 여러개의 Type variable을 쓸 수도 있습니다.
Generic Method
class ArrayHandle
{
public static <T> T getMiddle(T... a)
{
return a[a.length/2];
}
}
위와같이 Method도 Generic을 사용할 수 있습니다.
String middle = ArrayHandle.<String>getMiddle("A","B","C");
위 처럼 Method이름앞에 T 타입을 명시해줘야하지만 컴파일러가 알아서 해줍니다.
Bounds
class PairHandle
{
public static <T> String getMergedString(T pair){
return T.getFirst+T.getSecond; // Compile Error
}
}
위의 코드에서 에러가 나는 이유는 T타입이 정해지지 않았는데, T에 .getFirst(), .getSecond()가 정의되어 있는지 확신할 수 없기 때문입니다.
이와같은 문제를 해결하기 위해 Bounds를 사용합니다.
extends
public static <T extends Pair<String>> String......
위처럼 extends을 사용해서 T에는 Pair의 Sub type만 허용하도록 정의할 수 있습니다.
이때 extends 키워드는 상속받을 때 사용하는 extends와는 사용법도 조금 다른데, 의미적으로는 T가 subclass 라는 뜻이 아닌, Sub type임을 의미합니다. 또한 Interface도 받을 수 있습니다.
T extends Comparable & Cloneable
위 코드처럼 두 타입을 동시에 만족하는 타입만 받겠다는 의미로 사용할 수도 있습니다.
Wildcard
Generic간 상속관계
ArrayList<Manager> managerList= new ArrayList<>();
ArrayList<Employee> employeeList = new ArrayList<>();
employeeList.add(managerList); // Compile Error
Manager와 Employee는 상속관계에 있지만 제네릭으로 제한된 각 ArrayList끼리는 상속관계가 없기 때문에 Compile Error가 발생합니다.
이와 같은 문제를 해결하기 위해 Wildcard를 사용합니다.
[Java] Generic , Wild Card 정리
Generic이란?
ArrayList<String>
처럼 받는 타입을 제한하는 것입니다.사용하는 이유
각 타입별로 똑같은 코드를 짜지 않아도 되기 때문입니다.
예를 들어 이전의 ArrayList는 Object타입을 활용하여 만들어졌었고, 따라서 get할때 Casting이 필요했었습니다.
또한, Compile 단계에서 에러를 발생시켜 신뢰성있는 프로그램이 되도록 합니다.
차이점
기존의 방식
Generic
Generic Class
Pair라는 클래스가 위와 같이 정의되어있다면, Pair<String> pair = new Pair();처럼 인스턴스화 하게될때 Pair안의 T들은 모두 String으로 대치되게 됩니다.
위 처럼 여러개의 Type variable을 쓸 수도 있습니다.
Generic Method
위와같이 Method도 Generic을 사용할 수 있습니다.
위 처럼 Method이름앞에 T 타입을 명시해줘야하지만 컴파일러가 알아서 해줍니다.
Bounds
위의 코드에서 에러가 나는 이유는 T타입이 정해지지 않았는데, T에 .getFirst(), .getSecond()가 정의되어 있는지 확신할 수 없기 때문입니다.
이와같은 문제를 해결하기 위해 Bounds를 사용합니다.
extends
위처럼 extends을 사용해서 T에는 Pair의 Sub type만 허용하도록 정의할 수 있습니다.
이때 extends 키워드는 상속받을 때 사용하는 extends와는 사용법도 조금 다른데, 의미적으로는 T가 subclass 라는 뜻이 아닌, Sub type임을 의미합니다. 또한 Interface도 받을 수 있습니다.
위 코드처럼 두 타입을 동시에 만족하는 타입만 받겠다는 의미로 사용할 수도 있습니다.
Wildcard
Generic간 상속관계
Manager와 Employee는 상속관계에 있지만 제네릭으로 제한된 각 ArrayList끼리는 상속관계가 없기 때문에 Compile Error가 발생합니다.
이와 같은 문제를 해결하기 위해 Wildcard를 사용합니다.