[Java] Generic(제네릭)

Sun choi·2024년 8월 20일

NEW 지식

목록 보기
18/34

제네릭이란?!

타입 유연하게 다루기
제네릭(Generic)은 결정되지 않은 타입을 파라미터로 처리하고, 실제 사용할 때 파라미터를 구체적인 타입으로 바꾸는 기능이다. (Java 5에서 지원 시작)

제네릭의 효용

  • 첫 번째로 제네릭의 효용은 타입 언어에서 “중복되거나 필요 없는 코드를 줄여주는 것”이다.
  • 두 번째 제네릭의 효용은 그러면서도 타입 안정성을 해치지 않는 것이다.
// 1.
public class Generic<T> {
	// 2.
    private T t;
    // 3.
    public T get() {
        return this.t;
    }

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

    public static void main(String[] args) {
		// 4. <> 안에 들어가야할 타입을 명시,
        //이렇게 new 라고 정의하면 모든 <T>가 String타입으로 변환.
        Generic<String> stringGeneric = new Generic<>();
		// 5.
        stringGeneric.set("Hello World");
				
        String tValueTurnOutWithString = stringGeneric.get();

        System.out.println(tValueTurnOutWithString);
    }
}

제네릭은 클래스 또는 메서드에 사용가능

public class Generic<T> { ... }

Generic<String> stringGeneric = new Generic<>();
  • Generic의 클래스처럼, 제네릭을 사용한 클래스를 제네릭 클래스라고 한다.
  • 제네릭에서 <>사이에 들어가는 변수명 T는 타입 변수라고 한다.
  • Generic 클래스를 원시 타입이라고 한다.

제네릭의 제한

  • 객체에 static 멤버는 사용 불가
    타입 변수는 인스턴스 변수로 간주되고, 모든 객체에 동일하게 동작해야 하는 static 필드 특성상 사용할 수 없다.
  • 제네릭 배열 생성 불가
static T get() { ... } // 에러

static void set(T t) { ... } // 에러

타입 변수의 이름은 T?

✔️ 타입 변수의 이름을 T로 사용하는 이유는 일종의 컨벤션이기 때문이다.
당연히 컨벤션이기 때문에, 본인이 원하는 어떠한 변수를 넣어도 문제는 없다.
다만 당연히 컨벤션이기 때문에, 굳이 다른 이유가 없다면 T를 사용하는 게 협업에 유리하다. 이와 함께 자주 사용되는 변수명으로는 T,U,V, E 등이 있다.

Generic <T, U, E>
이렇게 다수의 타입변수 사용 가능.

public class Generic<T, U, E> {
  public E multiTypeMethod(T t, U u) { ... }
}

Generic<Long, Integer, String> instance = new Generic();
instance.multiTypeMethod(longVal, intVal);

제네릭의 문법

상속과 타입의 관계 가능

  • 부모 클래스로 제네릭 타입 변수를 지정하고, 그 안에 자식 클래스를 넘기는 것은 잘 동작한다.

와일드 카드

  • < ? extends T> T와 그 자손들만 사용가능
  • < ? super T> T와 그 조상들만 사용가능
  • < ?> 제한없음

메서드를 스코프로도 선언 가능
여기서 스코프(Scope)란 프로그램상에서 사용되는 변수들의 사용 가능한 범위이다.

제네릭 클래스 안에서만 제네릭 메서드를 사용가능한 게 아니라 메서드 자체만으로도 제네릭으로 만들수 있다.

static <T> void sort(List<T> list, Comparator<? super T> c) { ... }
  • 이렇게 반환 타입 앞에 <> 제네릭을 사용한 경우, 해당 메서드에만 적용되는 제네릭 타입 변수를 선언할 수 있다.
  • 타입 변수를 클래스 내부의 인스턴스 변수 취급하기 때문에 제네릭 클래스의 타입 변수를 static 메서드에는 사용할 수 없었지만, 제네릭 메소드의 제네릭 타입 변수는 해당 메소드에만 적용되기 때문에 메소드 하나를 기준으로 선언하고 사용할 수 있다.
  • 같은 이름의 변수를 사용했다고 해도 제네릭 메소드의 타입 변수는 제네릭 클래스의 타입 변수와 다르다. T는 표현의 방식일 뿐이다!
public class Generic<T, U, E> {
		// Generic<T,U,E> 의 T와 아래의 T는 이름만 같을뿐 다른 변수
    static <T> void sort(List<T> list, Comparator<? super T> c) { ... }
}

엄청나게 날린 글씨체지만 공부하면서 적은 메모 첨부..


참고 : Head First Java

profile
풀스택 개발자의 공부기록 📖

0개의 댓글