JAVA

[JAVA] 제네릭(Generics) (자바 독학하기24)

자라는레몬 2021. 7. 22. 22:03
반응형

1. 제네릭 클래스

 

제네릭이 등장한 이후에 자료형에 의존적이지 않은 클래스를 정의할 수 있게 되었다.

제네릭을 이용해 클래스 내부에서 사용하는 데이터 타입을 인스턴스 생성시에 정의할 수 있다.

제네릭 기반의 클래스 정의는 다음과 같다.

class Classname <T>{

     public T val;

     public void methodname (T value){

     }

}

위와 같이 class 이름 뒤에 <T> 를 붙이고 클래스 내부에서 인자들 앞에 T 를 붙인다.

이렇게 정의된 제네릭 기반 클래스는 다음과 같이 인스턴스 생성을 한다.

Classname<String> cn = new Classname<String>();

위에서 사용한 T 를 가리켜 타입 매개변수라 하며 String 을 타입 인자, Classname<String> 을 가리켜 매개변수화 타입 이라고 한다.

- 타입 매개변수 (Type Parameter)                                          T

- 타입 인자 (Type Argument)                                                String

- 매개변수화 타입 (Parameterized Type or Generic Type)            Classname<String>

 

또한 제네릭은 다중 매개변수로 정의가 가능하다.

class Classname <T, E>

와 같이 사용할 수 있다.

 

매개변수화 타입을 구성할 때 기본 자료형은 타입 인자로 사용할 수 없다. (ex. int)

그러나 상기 예에서 사용 했듯이 래퍼 클래스는 사용이 가능하다. (ex. Integer)

 

Classname<String> cn = new Classname<String>();

과 같이 선언된 인스턴스는 우측의 <> 안의 값을 생략할 수 있다.

이는 컴파일러가 좌측의 매개변수를 통해 알아서 인식하기 때문이다.

따라서 이는

Classname<String> cn = new Classname<>();

과 같이 생략이 가능하다.

 

매개변수화 타입을 타입 인자로 사용 할 수도 있는데 이는

Classname<Calssname<String>> cn = new Classname<>();

과 같이 사용할 수 있다는 의미이다.

 

제네릭 클래스의 타입 인자를 제한할 수 있는 방법이 있는데 extends 를 사용하는 것이다.

class Classname <T extends Number>{ ... }

와 같이 사용하면 인스턴스 생성 시에 타입 인자로 Number 또는 이를 상속하는 클래스만 올 수 있다.

이와 유사하게 인터페이스로도 타입 인자를 제한할 수 있는데 인터페이스를 선언 후 구현한 후에

class Classname <T extends Interfacename>{ ... }

와 같이 사용하면 된다.

타입 인자 제한을 하나의 클래스와 하나 이상의 인터페이스에 대해 동시에 할 수 있는데 방법은 다음과 같다.

class Classname <T extends Number & Interfacename>{ ... }

 

2. 제네릭 메소드

 

제네릭 정의를 클래스 전부에 하는 것이 아닌 특정 메소드에만 할 수도 있다.

public static <T> Otherclass<T> methodname(T val) { ... }

public static <T> T methodname(Otherclass<T> val) { ... }

과 같이 사용한다.

 

3. 와일드 카드

 

먼저 제네릭 메소드의 표현은 다음과 같다.

public static <T> void methodname (Otherclass <T> val) { ... }

그리고 이와 동일한 기능을 하는 와일드 카드 기반 메소드는 다음과 같다.

public static void methodname (Otherclass<?>  val) { ... }

이와 같이 동일한 코드지만 코드가 조금 더 간결한 코드로 구성된다.

와일드 카드는 제네릭 타입의 상속관계를 형성하기 위해 사용된다.

 

이러한 제네릭 타입의 상속 관계를 통해 상한 제한과 하한 제한을 걸 수 있다. (Bounded Wildcards)

상한 제한 와일드 카드(Upper-Bounded Wildcards)는 다음과 같이 매개 변수를 설정한다.

- Class<? extends Number> val

이는 Class<T> 에서 T Number 또는 Number 의 하위 클래스인 제네릭 타입의 인스턴스만 전달되도록 제한할 때 사용한다.

이와 유사하게 하한 제한 와일드 카드(Lower-Bounded Wildcards)의 매개 변수 설정은 다음과 같다.

- Class<? super Integer> val

이는 Class<T> 인스턴스의 T 가 Integer 또는 Integer 가 상속하는 클래스여야 한다.

반응형