자바/지네릭스

지네릭 메서드

백_곰 2022. 5. 13. 13:49

1. 지네릭 메서드란?

- 메서드의 선언부에 지네릭 타입이 선언된 메서드를 '지네릭 메서드' 라고 부른다.

 

- 앞서 했던 예제 메서드 Collections.sort() 또한 지네릭 메서드이다.

 

- 지네릭 클래스에 정의된 타입 매개변수와 지네릭 메서드에 정의된 타입 매개변수는 전혀

별개의 것이다.

 

 

- 아래의 코드를 통해 이해하자.

class FruitBox<T>{
     ...
     static <T> void sort(List<T> list, Comparator<? super T> c){
          ...
     }
}

 

( 위의 FruitBox의 <T>static <T>와는 문자만 같을 뿐 서로 다른 것이다. )

 

( sort()는 static 멤버인데, 원래는 변수에 지네릭을 쓸 경우 static을 줄 수 없다. )

( 그러나, 메서드에 지네릭 타입을 선언하고 사용하는 것은 가능하다. )

 

( 메서드에 선언된 지네릭 타입은 지역 변수를 선언한 것과 같다. )

( 이 타입 매개변수는 메서드 내에서만 사용할 것이기 때문에, static이건 아닌건 상관없다. )

 

 

 

- 앞서 사용했던 메서드 makeJuice()를 지네릭 메서드로 바꾸면 아래와 같다.

적용 전 적용 후
static Juice makeJuice(FruitBox<? extends Fruit> box){
      String tmp = "";
      for(Fruit f : box.getList()) tmp += f+" ";
      return new Juice(tmp);
}
static <T extends Fruit> Juice makeJuice(FruitBox<T> box){
      String tmp = "";
      for(Fruit f : box.getList()) tmp += f+" ";
      return new Juice(tmp);
}

 

 

( 위 지네릭 메서드를 호출하면 아래와 같다. )

FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();

System.out.println(Juicer.<Fruit>makeJuice(fruitBox);
System.out.println(Juicer.<Apple>makeJuice(appleBox);

 

 

( 그러나 대부분의 경우 컴파일러가 타입을 추정할 수 있기 때문에 생략이 가능하다. 아래의 코드를 보자. )

System.out.println(Juicer.makeJuice(fruitBox);
System.out.println(Juicer.makeJuice(appleBox);

 

 

( 한 가지 주의할 점은 지네릭 메서드를 호출할 때, 대입된 타입을 생략할 수 없는 경우에는 참조변수나

클래스 이름을 생략할 수 없다는 것이다. 아래의 코드를 보자. )

System.out.println(<Fruit>makeJuice(fruitBox));
// 에러 발생

System.out.println(this.<Fruit>makeJuice(fruitBox));
System.out.println(Juicer.<Fruit>makeJuice(fruitBox));
// 위 두 코드 정상 컴파일

 

 

( 지네릭 메서드는 매개변수의 타입이 지네릭으로 인해 복잡할 경우에도 간단한게 써줄 수 있다. 아래의 코드를 보자. )

 

< 적용 전 >

public static void printAll(ArrayList<? extends Product> list, ArrayList<? extends Product> list2){
         ...
}

 

< 적용 후 >

public static <T extends Product> void printAll(ArrayList<T> list, ArrayList<T> list2){
         ...
}

 

 

 

( 마지막으로 아래의 예제 코드를 보자. )

public static <T extends Comparable<? super T>> void sort(List<T> list)

 

 

( 위와 같은 코드가 나오면, 일단 아래의 코드처럼 와일드 카드를 걷어내보자. )

public static <T extends Comparable<T>> void sort(List<T> list)

 

( 위 문장은 List<T>가 Comparable 인터페이스를 구현한 것이어야 한다는 뜻이다. )

 

( 예를 들어, Student가 T이고 Person의 자손이라면, <? super Student>는 Student, Person, Object 모두가

가능하다는 뜻이다. )