JAVA

[JAVA] Generic

개발 공주 2023. 6. 14. 17:30
728x90

제네릭(Generic)은 직역하자면 '일반적인'이라는 뜻이다.

'데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법'이다.

 

제네릭(Generic)은 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 의미한다. 한마디로 특정(Specific) 타입을 미리 지정해주는 것이 아닌 필요에 의해 지정할 수 있도록 하는 일반(Generic) 타입이라는 것이다.

 

 

Generic(제네릭)의 장점

1. 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.

2. 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없다. 즉, 관리하기가 편하다.

3. 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.

 

Generic(제네릭) 문법 살펴보기

제네릭 용어 정리하기

public class Generic<T> { ... }

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

<> 안에 들어가는 타입변수들

타입 설명
<T> Type
<E> Element
<K> Key
<V> Value
<N> Number

반드시 한 글자일 필요는 없다. 또한 설명과 반드시 일치해야 할 필요도 없다.

<Hello>라고 해도 전혀 무방하다. 다만 대중적으로 통하는 통상적인 선언이 가장 편하기 때문에 위와같은 개발자들의 암묵적인 규칙이 있다.

 

제네릭의 제한

1. 객체의 static 멤버에 사용 할 수 없습니다.

static T get() { ... } // 에러

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

 

타입 변수는 인스턴스 변수로 간주되고, 모든 객체에 동일하게 동작해야하는 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> { ... }

ParkingLot<BMW> bmwParkingLot = new ParkingLot();
ParkingLot<Iphone> iphoneParkingLot = new ParkingLog(); // error!
  1. <? extends T> : T와 그 자손들만 사용 가능
  2. <? super T> : T와 그 조상들만 가능
  3. <?> : 제한 없음

📌 이렇게 제한을 하는 이유는 다형성 때문입니다. 위의 코드에서, T는 Car의 자손클래스들이라고 정의했기 때문에, 해당 클래스 내부에서 최소 Car 객체에 멤버를 접근하는 코드를 적을 수 있습니다. 반대로 그러한 코드들이 있을 여지가 있기 때문에, Car 객체의 자손이 아닌 클래스는 제한하는 것

 

4. 메서드를 스코프로 제네릭을 별도로 선언 할 수 있습니다.

출처 : Head First Java

// 또는 ..
static <T> void sort(List<T> list, Comparator<? super T> c) { ... }
  1. 이렇게 반환 타입 앞에 <> 제네릭을 사용한 경우, 해당 메서드에만 적용되는 제네릭 타입변수를 선언 할 수 있습니다.
  2. 타입변수를 클래스 내부의 인스턴스 변수 취급하기 때문에 제네릭 클래스의 타입변수를 static 메서드에는 사용 할 수 없었지만, 제네릭 메소드의 제네릭 타입 변수는 해당 메소드에만 적용되기 때문에 메소드 하나를 기준으로 선언하고 사용 할 수 있습니다.
  3. 같은 이름의 변수를 사용했다고 해도 제네릭 메소드의 타입변수는 제네릭 클래스의 타입변수와 다릅니다.
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

'JAVA' 카테고리의 다른 글

[JAVA] 예외 처리 (4)  (0) 2023.06.14
[JAVA] 예외 처리 (3)  (0) 2023.06.13
[JAVA] 예외 처리 (2)  (0) 2023.06.13
[JAVA] 예외처리 (1)  (0) 2023.06.12
[JAVA] 인터페이스 다형성  (0) 2023.06.01