Java 제네릭 이해하기

‍박태우·2024년 9월 5일

nbc_spring

목록 보기
10/28

1. 제네릭의 필요성

  • java 는 타입이 있는 언어이다.

=> 메서드에서 input 타입이 필요 아래와 같이 한다면 된다고 생각 할 수 있다.

public void exampleMethod(Object a, Object b){
...
}

=> 가능은 하지만 이런식으로 되면 a, b 에 특정 타입의 변수가 들어오면 형변환을 일일이 해줘야 하는 귀찮음이 존재한다. (제네릭을 쓰면 된다!!)


2. 제네릭 사용 예시

// 1. 제네릭은 클래스 또는 메서드에 사용가능
// <> 안에 들어가야 할 타입을 명시
public class Generic<T> {
    // 2. 내부 필드에 String
    private T t;
    // 3. 메서드의 return 타입도 String
    public T get() {
        return this.t;
    }

    public void set(T t) {
        this.t = t;
    }

    public static void main(String[] args) {
        // 4. 위 T 가 String이 된다.
        Generic<String> stringGeneric = new Generic<>();
        // 5. String을 매개변수로 받음
        stringGeneric.set("Hello World");

        String tValueTurnOutWithString = stringGeneric.get();

        System.out.println(tValueTurnOutWithString);
    }
}

위 코드에서 T 자리에 String, Integer 와 같은 데이터 형의 Wrapper 클래스가 들어가게 된다. T는 다른 문자로 선언해도 되지만 개발자 집단 에서는 보통 T가 사용된다.


3. 제네릭 문법 이해하기

public class Generic<T>{...}
Generic<String> stringGeneric = new Generic<>();

Generic<T> 의 클래스 처럼 제네릭을 사용한 클래스가 제네릭 클래스 이다.
T 는 타입변수라고 하며, Generic 클래스를 원시타입 이라고 한다.

-제한 사항
1) 객체의 static 멤버에 사용 불가 (타입변수가 인스턴스 변수로 간주 되기 때문)
2) 제네릭 배열은 생성 할 수 없다.

-특징
1) 다수의 타입변수를 사용 할 수 있다.

public class Generic<T, U, E> {
public E multiTypeMethod(T t, U u) { ... }
}
Generic<Long, Integer, String> instance = new Generic();
instance.multiTypeMethod(longVal, intVal);

2) 다형성 즉 상속과 타입관계는 그대로 적용된다.
-> 부모 클래스로 제네릭 타입변수를 지정하고 그안에 자식클래스를 넘기는 것은 잘 동작한다.

3) 와일드 카드를 통해 제네릭의 제한을 구체적으로 정할 수 있다.

public class ParkingLot<T extends Car>{...}

(3-1) 와일드 카드란?

  1. <? extends T> : T와 그 자손들만 사용 가능
  2. <? super T> : T와 그 조상들만 가능
  3. <?> : 제한 없음

=> 위에서 볼수 있듯이 Car 클래스를 상속받은 BMW는 가능하지만 그렇지 않은 Iphone 은 불가능하다는 것을 알 수 있다.

4) 메서드를 스코프로 제네릭 별도 사용 가능 (꼭 제네릭 클래스 내부만 가능한 것이 아니다.

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

=> 제네릭 메소드의 제네릭 타입 변수는 해당 메소드에만 적용되기 때문에 메소드 하나를 기준으로 선언하고 사용 할 수 있다.
(class 는 같인 타입변수를 쓰는 제네릭이 아닌 경우 가능)

5) 아래와 같은경우의 T는 서로 다른것이다. 위에서 클래스 스코프와 메서드 스코프 마다 다르게 적용되는 이유 때문

public class Generic<T, U, E> {
// Generic<T,U,E> 의 T와 아래의 T는 이름만 같을뿐 다른 변수
static <T> void sort(List<T> list, Comparator<? super T> c) { ... }
}
profile
잘 부탁드립니다.

0개의 댓글