[Java] Generic(제네릭) 정리
Generic
자바독을 보게되면 정말이지 제네릭 표현이 많다. 이 개념을 모르면 자바독을 참고할 때 API가 어떻게 쓰이는지 보기가 참 힘들다. 추가적으로 람다형식의 함수형으로 푼 형태도 많이 있는데 이 개념은 나중에 정리하고 이번에는 제네릭만 정리를 해보려고 한다.
역사적으로는 Java 5부터 사용이 되었다. 특히나 NIO, 컬렉션, 람다식, 스트림을 많이 사용하는 사람이라면 필수적으로 알아야 된다. 정말 너무 많이 나온다.
쓰는 이유?
가장 큰 이유는 잘못된 타입이 사용될 수 있는 경우 컴파일 과정에서 걸러주는 역할이다.
메소드를 정의 할 때, 타입이라는 것을 파라미터로 사용할 수 있게끔 하는 역할인데 이런 이유는 코드를 작성 시에 구체적으로 다시 만들 수 있도록 하기 위한 장치이다.
특히나 캐스트로 타입 변환되는 과정이 있다면 이것은 성능에 굉장히 오버헤드가 되기 때문에 이러한 것을 걸러내기 위한 장치이기도 하다. (아래 코드 참고)
1
2
3
|
List list = new ArrayList();
list.add("whitekeyboard");
String str = (String) list.get(0); //이렇게 캐스팅 되는 것을 볼 수 있다.
|
cs |
형식 - (1) : 타입
위에서 캐스팅으로 성능 저하가 발생하는데 해결하려면 아래와 같이 작성해야 된다.(아래 코드 참고) 여기서 볼 수 있듯이 형식은 클래스나 인터페이스 뒤에 "< >"(다이아몬드 연산자)라는 부호가 붙여서 안에 타입을 정의하는 형식이다.
선언 형식은 정해진 것은 없지만 타입(T), 엔티티(E) 형식으로 일반적인 가이드라인은 존재한다. 구글링하면 많이 나오니 참고. 보통 자바독에서 클래스 위에 주석으로 설명을 해주기 때문에 첫글자를 따서 만든 것이라고 보면 된다.
1
2
3
|
List<String> list = new ArrayList<String>();
list.add("whitekeyboard");
String str = list.get(0);
|
cs |
형식 - (2) : 멀티 파라미터
멀티도 단일과 비슷한데 콤마를 통해서 멀티 타입을 제공한다. "<K, V>" 그리고 자바7 이후에는 인스턴스를 생성할 때 Test<Key, String> test = new Test<>();로 "<Key, String>"이 앞 뒤 붙여주질 않아도 알아서 뒤에도 매핑시켜 준다.
1
2
3
|
Keyboard<Paper, String> keyboard = new Keyboard<Paper, String>(); // 전통적인 방식
Keyboard<Paper, String> keyboard = new Keyboard<>(); // JDK1.5부터 가능
Keyboard keyboard = new Keyboard(); // JDK1.7부터 가능
|
cs |
형식 - (3) : 메소드
제네릭 메소드는 내가봐도 헷갈리는데 한번 정리를 잘 해놓으면 다음부터는 그나마 친숙함이 들어서 이해하기 쉬워질지도..모른다. 일단 형식은 아래와 같이 함수가 선언이 되는데, 리턴값과 파라미터값 그리고 특이한 제네릭 타입이 정해져 있어 혼란을 가중한다. 메소드에서 제네릭을 사용하는 이유는 클래스의 제네릭 타입이 전역 변수처럼 사용된다면 메소드의 제네릭 타입은 해당 메소드 안에서만 사용할 수 있는 지역성을 갖는다.
위에 보이는 초록색 네모상자 T와 파란색 네모상자 T는 같아 보이지만 다른 것이다. 리턴값은 기본적인 형태와 유사해서 바로 이해할 수 있겠는데, 저 초록색 제네릭 타입은 무엇일까? 이것은 이 메소드에서만 사용되는 제네릭 타입의 지역 제네릭 타입이다. 이와 반대로 클래스 제네릭은 전역변수라고 생각하면 되겠다.
이렇게 선언되는 이유는 컴파일 시, 컴파일러가 매개 변수 타입을 추정할 수 있도록 제네릭 타입을 명시하는 이유이다. 인스턴스를 할당해서 클래스에 속한 함수를 사용하게 되면 그 이유를 단번에 알 수 있을 것이다.
결론은 제네릭 메서드를 사용하려면, 초록색 상자인 제네릭 타입을 선언해야한다. 선언하지 않으면 컴파일 시 에러가 발생하는데 에러가 발생하는 예제의 코드는 아래와 같다.
1
2
3
4
|
// 컴파일 에러 코드 예제
public static White<T> from(T name) {
return new White<>(name);
}
|
cs |
참고 :
- https://devlog-wjdrbs96.tistory.com/201
- http://www.tcpschool.com/java/java_generic_concept
- https://smoothiecoding.kr/%EC%9E%90%EB%B0%94-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4/
- https://atoz-develop.tistory.com/entry/JAVA-%EC%A0%9C%EB%84%A4%EB%A6%ADGenerics-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EB%A9%94%EC%86%8C%EB%93%9C