제이제이
124
2018-06-17 10:44:56
3
1785

지네릭 메서드(Generic Method)의 사용 이유가 무엇일까요?


안녕하세요 자바를 공부하는 대학생입니다

지네릭 메서드에 대해 공부하다가 왜 지네릭 메서드를 써야하는지에 대한 이유를 찾지 못해 질문드립니다.

제가 알아본 바로는 지네릭 메서드를 사용하는 이유는 메서드의 매개변수의 타입이 복잡할 때 유용하게 사용

할 수 있다고 합니다. 


지네릭 클래스의 경우는 데이터의 안정성을 높인다는 것에서 장점이 있지만 지네릭 메서드는 특별한 사용이유를 찾지 못해서 질문드립니다

2
0
  • 답변 3

  • LichKing
    15k
    2018-06-17 11:06:11

    사용 이유는 제네릭 클래스랑 비슷한데요. 제네릭 클래스는 사용하는 입장에서 제네릭 타입을 명시해야되지만 제네릭 메서드는 좀 더 유연한 타입추론을 지원해서 사용하는 입장에서 제네릭 메서드인지 모르게 사용할수도있어 더 권장하는 편입니다.


    String list와 추가할 문자열을 인자로받아 add를 실행하고, 그 리스트를 다시 리턴하는 메서드가 있다고 생각해봅시다.

    private static List<String> add(List<String> list, String element) {
    list.add(element);

    return list;
    }

    이런 형태가 될겁니다. 그런데 꼭 String 이 아니라 Integer list도 대응하게하고싶습니다.

    그런데 저 메서드에는 List<Integer> 를 전달하면 컴파일 에러가 발생합니다.

    private static List<Integer> add(List<Integer> list, Integer element) {
    list.add(element);

    return list;
    }

    이런 메서드를 하나 더 오버로딩 할수도 있겠지만... 제네릭을 사용하면 하나의 메서드로 String, Integer 외에도 모든 타입에 대응할 수 있게 만들 수 있습니다.

    private static <T> List<T> add(List<T> list, T element) {
    list.add(element);

    return list;
    }


    이펙티브자바에서는 저 형태의 메서드가 공개된 인터페이스(public) 일땐 저 메서드를 와일드카드로 공개하게 권하고 있는데 그건 좀 더 깊은 얘기니... 저런 형태로 활용이 가능하고요.

    쪼끔 더 나아가 저 예제에서 List가 아니라 Collection에 대응하게하고싶다고 가정해봅시다. 단, 리턴할때는 Collection이라는 추상화된 타입이 아니라 인자로 들어오는 구현타입으로 리턴을 하고싶습니다.

    private static <T> Collection<T> add(Collection<T> list, T element) {
    list.add(element);

    return list;
    }

    이렇게 만들면 쉽게 Collection에도 대응할 수 있지만 두번째 요구사항인 '인자로 들어오는 구현타입으로 리턴'을 충족시키지 못합니다. 저렇게 만들면 메서드를 호출하는 쪽에서 항상 타입캐스팅을 해줘야합니다.

    List<String> list = new ArrayList<>();
    List<String> addList = add(list, "hello"); // Collection을 리턴하기때문에 컴파일 에러발생
    List<String> addList = (List<String>)add(list, "hello"); // 이렇게 타입변환을 해야함


    이런 경우에도 제네릭 메서드를 이용하면 저런 타입캐스팅 코드를 없앨 수 있습니다.

    private static <T, R extends Collection<T>> R add(R collection, T element) {
    collection.add(element);

    return collection;
    }

    이런식으로 구현하면 List가 들어오면 List를 리턴하고, Set이 들어오면 Set을 리턴하게되어 클라이언트에서 타입캐스팅을 할필요가 없어집니다.


    당장 생각나는 간단한 예제가 이정도네요.

    2
  • SDuck
    843
    2018-06-17 11:07:29

    어떤 클래스를 구현할 때 제네릭으로 하면 어떤 클래스던 멤버가 될 수 있는 장점이 있죠.

    예를들어 컬렉션이 제네릭으로 선언되지 않았다면, 내가 만든 클래스를 리스트나 맵에 넣을 수 없겠죠?

    멤버변수를 모든 클래스의 부모인 Object로 만든다면, 가능은 하겠지만 사용할 때 형변환을 해줘야 하기 때문에 귀찮을 거구요.

    그래서 만들어진게 제네릭입니다.

    1
  • NortonSimon
    85
    2018-06-17 15:55:39

    flydof// 이유를 생각해 보는 건 '매우' 좋은 습관입니다.

    1
  • 로그인을 하시면 답변을 등록할 수 있습니다.