만쥬의 개발일기
article thumbnail

제네릭 메서드(Generic Method)란?

자바(Java)에서 제네릭(Generic)은 클래스 내부에서 사용하는 데이터의 타입(Type)을 클래스의 인스턴스를 생성할 때 결정하는 것을 의미한다. 객체의 타입을 컴파일 시점에 체크하기 때문에 타입 안정성을 높이고 형 변환의 번거로움을 줄일 수 있다.

 

즉, 제네릭 메서드는 메서드의 선언 부에 적은 제네릭 타입으로 리턴 타입과 파라미터 타입이 모두 정해지는 메서드이다.

 

우선 제네릭에 대한 여러 예시를 보며 이해해보자.

public class Student<T> {
    static T name;
}

위와 같이 작성할 경우, 제네릭을 사용할 수 없다.

왜냐면, static 변수는 Student 클래스가 인스턴스가 되기 이전에 메모리에 올라가는데, 이 때 name의 타입인 T가 결정되지 않았기 때문에 사용이 불가능한 것이다.

 

static이 가능한 제네릭 메서드

위와 같이 제네릭 클래스에서 static 변수는 사용이 불가능한데, 이럴 때 사용하는 것이 제네릭 메서드이다. 제네릭 메서드는 호출 시에 매개변수 타입을 지정하기 때문에 static이 가능한 원리다.

public class Student<T> {
    
    static <T> T getStudentName(T name) {
        return name;
    }
}

위와 같이 메서드의 return type 앞에 제네릭을 사용해주면 된다. 

여기서 주의할 점은

Student 클래스에 지정한 제네릭 타입 <T>와, 제네릭 메서드에 붙은 <T>는 같은 T일지라도 서로 별개라는 것이다.

 

제네릭 메서드를 사용할 경우 T가 지역변수로 바뀐다.

public interface List<E> extends Collection<E> {
    boolean add(E e);
}

위 예시의 경우는, Collection을 List가 상속받고, add 메서드만 가져온 모습이다.

이때의 List 제네릭 타입인 E와 add 메서드의 매개변수 타입 E는 동일하다.

 

위에서 제네릭 메서드를 사용할 때만 별개의 타입이고, 위 같이 사용할 경우는 같은 타입 것이다.

 

제네릭 메서드 사용법 예시

public class Box<T> {
    private T t;
    
    public T getT() {
        return t;
    }
    
    public void setT(T t) {
        this.t = t;
    }
}
public class Util {
    
    public static<T> Box<T> boxing(T t) {
        Box<T> box = new Box<T>();
        box.setT(t);
        return box;
    } 
 }
public class Main {
    public static void main(String[] args) {
        Box<Integer> box1 = Util.<Integer>boxing(100);
        
        Box<String> box2 = Util.boxing("암묵적호출");
    }
}

제네릭 메서드를 호출할 때에는 타입을 정하는 2가지 방법이 있다.

  • Main 클래스에서처럼 호출할 때 타입을 지정하는 방법
  • 호출할 때 타입을 지정하지 않는 방법

첫번째 경우는 컴파일러가 <Integer>를 보고 타입을 지정한다.

두번째 암묵적 호출의 경우는 매개변수 타입이 String인 것을 보고 컴파일러가 타입을 추론한다.

 

제네릭 클래스 vs 제네릭 메서드

즉, 형식과 사용이 제네릭 클래스와 동일하지만, 제네릭 클래스의 <T>와 제네릭 메서드의 <T>는 다르다는 것만 유념하자.

그리고 제네릭 메서드는 해당 메서드를 포함한 클래스가 제네릭이 아니어도 사용이 가능하다.

class Student<T>{

    public T getOneStudent(T id){ return id; }  // 1
    
    public <T> T getId(T id){return id;} // 2 제네릭 클래스의 T와 다름  
    
    public <S> T toT1(S id){return id; }  // 3
    
    public static <S> T toT2(S id){return id;}  // 4 에러 
}
  • 1번의 경우 클래스의 제네릭 타입 T를그대로 사용하는 경우다.
  • 2번의 경우 클래스의 제네릭 타입 T와 제너릭 메소드 타입 T는 다르다.
  • 3번의 경우 static 메서드가 아닌 일반 메서드기 때문에 클래스의 타입과 제네릭 메서드의 타입을 같이 사용가능하다.
  • 4번의 경우 static 메서드기 때문에 클래스의 제네릭 타입 T를 사용하므로, 에러가 발생한다. 이 때는 타입 S만을 사용해야 한다.

 

reference

profile

만쥬의 개발일기

@KangManJoo

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!