본문 바로가기
개발/자바

자바 (제네릭, Generic)

by EPdev 2020. 5. 8.
728x90

*** 이 개념은 "이것이 자바다. 신용권의 Java 프로그래밍 정복" 을 보고 정리한 것입니다. ***

 

채팅을 구현하려고 TCP, socket 등을 공부하다가 이상한 길로 새어

제네릭(Generic)이란 개념을 보게 되었다. 

 

이전에 개발하면서 계속 써왔던 것인데, 이게 제네릭인줄은 이번에 처음 알았다.

그냥 많이 봤던 걸 예시로 들어주면

Hashmap<String, String> hashmap = new Hashmap<>();

이런 거다. 여기서 어떤게 제네릭이냐면 다이아몬드 연산자 <> 로 표현된 부분이다.

 

그렇다면 제네릭은 왜 사용하는가 ?

1. 타입 에러를 강하게 체크한다고 함.. 나중에 실행중에 타입 에러가 뜨는걸 막기 위해 컴파일 할때 부터 강하게 타입체크를 함

2. 타입 변환(Casting)을 제거한다고 함.. 비제네릭 코드는 타입 변환이 필요한 경우가 많은데, 제네릭 코드는 이걸 막아준다고 함.

** 형변환은 많을 수록 프로그램 성능에 좋지 못하다. **

예를 들어

List list = new ArrayList();
list.add("test");
String str = (String) list.get(0);
// 리스트에서 값을 뽑아 String 변수로 줄 때, (String) 이 붙어 타입변환이 일어남

이와 반면에 제네릭 코드를 사용하면

List<String> list = new ArrayList<String>();
list.add("test");
String str = list.get(0);
// 타입 변환이 필요 없음.


//참고로 자바7 부터는 <> 연산자만 사용해도 타입을 자동으로 유추해준다.
//위 코드의 첫번 째 줄을 아래처럼 써도 된다는 뜻.
List<String> list = new ArrayList<>();

이런 식으로 사용이 가능해진다는 것이다.

 

"제네릭 타입"이란 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.

public class 클래스이름<T> {...}
public interface 인터페이스이름<T> {...}

// T 에는 변수명과 동일한 규칙에 따라 작성할 수 있지만, 보통은 영대문자 1자로 작성한다.

이렇게 사용하는 이유는 위에서 언급했던 것 처럼.. 타입의 변환을 줄이기 위해서다.

가령

public class test{
    private Object object;
    public void set(Object object) { this.object = object; }
    public Object get() { return object; }
}

이러한 클래스가 있다고 치자. 이 클래스로

Test test = new Test();

이렇게 객체를 만들어서 사용한다면

String 값을 get 하거나 set 해줄 때, Object <-> String 형 변환이 일어나고

Int 값을 get/set 해줄 땐, Object <-> Int 형 변환이 일어난다.

 

따라서 형변환을 최소화 하려면

public class test<T>{
    private T t;
    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

이런 식으로 클래스를 만들어 주는 것이다. 그리고

Test<String> test = new Test<>();
Test<Integer> test1 = new Test<>();

이런 식으로 객체를 만들어 준다면.. test, test1 객체에 get, set 해줄 때 형변환 해줄 수요가 줄어든다.

(물론 코딩을 하다보면 이보다 많은 변수를 가진 클래스가 나오니 잘 써야하겠지만..)

 

더 발전하면,

처음에 보여준

Hashmap<String, String> hashmap = new Hashmap<>();

이건 멀티 타입 파라미터라고 하며, 보는 것처럼 제네릭 타입을 두 개 이상 사용할 수 있다. (컴마로 구분)

 

제네릭 메소드도 있다. 많이 사용할 것 같진 않아서 있다는 정도로만 기억하고 필요할 때 찾아보자.

 

제한된 타입 파라미터

<T extends 최상위타입> 이런 식으로 표현하는데.. 예를 들어 "최상위타입"에 Number가 들어가면

그 타입으로는 Number를 포함한 하위 타입(Byte, Short, Integer, Long, Double) 등이 자유롭게 들어올 수 있다는 것이다.

 

와일드카드 타입 <?> , <? extends ...> , <? super ...>

구체적인 타입을 지정하기 보다.. 와일드카드처럼 범위가 넓게 쓰겠다는 것이다.

<?> 는 모든 클래스나 인터페이스 타입이 올 수 있다.

<? extends ...> 는 상속처럼 ... 에 명시된 클래스와 자식 클래스를 사용할 수 있다.

<? super ...> 는 ...에 명시된 클래스와 그 부모 클래스를 사용할 수 있다.

 

제네릭 타입의 상속과 구현은 필요할 때 찾아보자.

기본적으로는 상속 관계에서 제네릭 타입도 <T> 상속받고 한다는 개념이다.

728x90

'개발 > 자바' 카테고리의 다른 글

쓰레드 (Thread)  (0) 2020.05.22
인터페이스와 추상클래스 - Interface and Abstract Class  (0) 2020.05.22
클래스 (Class)  (0) 2020.05.21
JavaFX  (0) 2020.05.17
자바 (람다식, Lambda Expression)  (0) 2020.05.08

댓글