> For the complete documentation index, see [llms.txt](https://leehyokyun.gitbook.io/openbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://leehyokyun.gitbook.io/openbook/1-8.-java.md).

# 1-8. Java 언어의 깊이: 제너릭

Java를 깊이 있게 활용하기 위한 방법, 제너릭에 대하여

### 1. 제너릭 기초 선언 및 사용 범위 지정

* 제너릭 기호 기입은 이제 특정 제너릭을 정의하고 이를 Type Safe하게 사용하겠다는 선언의 의미를 가진다.
* 선언된 기호 자체는 지정된 제너릭 타입을 실제 코드로 사용하겠다는 의미다.
  * ```
    public T identity (T value) { 
        return value; 
    }
    ```
* 위 코드는 T 제너릭 선언 후, T 타입의 매개변수를 받아 그대로 T 타입으로 반환한다.
* 제너릭을 어디에 선언하느냐에 따라 어느 범위에서 사용할 수 있는지 사용 범위를 지정한다.
* 클래스 제너릭: 클래스에 제너릭을 선언하여 클래스 전체적으로 사용 가능하다.
* 메서드 제너릭: 메서드의 매개변수 및 반환 타입으로 사용 가능하다.

### 2. Class T와 Class\<?>의 정의 및 리플렉션(Reflection) 응용 차이

* Class T는 반환 타입의 일관성을 보장한다.
* 특정 타입 T의 Class로서 Type Safe한 Reflection을 가능하게 한다. 즉, 컴파일러가 반환 타입을 확실하게 인지한다.
  * ```
    public T createInstance(Class clazz) throws Exception { 
        return clazz.getDeclaredConstructor().newInstance(); 
    } 

    String s = createInstance(String.class); // T는 String으로 결정됨
    ```
* Class\<?>는 와일드카드 형태로 표현되며, 반환 타입의 일관성 보장이 불가능하다.
* 어떤 타입이든 올 수 있지만 구체적인 타입을 알 수 없으므로, 내부에서 특정 타입을 강제하거나 안전하게 새 인스턴스를 반환받아 일관되게 처리하는 리플렉션 연산에는 부적합하다.
  * <pre><code>public void printClassName (Class&#x3C;?> clazz) { 
        System.out.println(clazz.getName()); 
    <strong>} 
    </strong>
    printClassName(String.class);
    </code></pre>

### 3. 제너릭의 무공변(Invariant) 특성과 한계

* 제너릭은 기본적으로 무공변(Invariant)이다.
* 단일 관계로 선언한 무공변 제너릭은 클래스의 상속 관계가 존재하더라도 제너릭 타입 간의 상속 관계를 인정하지 않으며 적용할 수 없다.
* 코드 예시: public class Animal {} public class Cat extends Animal {}

  List animals = new ArrayList(); // 컴파일 에러 발생 List cats = new ArrayList(); // 컴파일 에러 발생
* 무공변 특성은 컴파일 시점의 타입 안정성은 확실하게 보장할 수 있으나, 다형성을 활용한 타입의 유연성을 보장할 수 없다는 치명적인 한계를 가진다.

### 4. \<T extends clazz> 와 \<? extends clazz>의 개념적 차이 및 활용

* 무공변을 해결하고 타입을 제한하기 위해 extends 키워드를 사용하지만, 선언 위치와 대상이 다르다.
* \<T extends clazz>는 한정적 타입 매개변수(Bounded Type Parameter) 선언이다. 특정 클래스나 인터페이스를 상속받은 타입으로만 T를 제한한다. 내부에서 T라는 타입을 명확히 인지하여 반환 타입이나 지역 변수로 안전하게 활용할 수 있다.
* \<? extends clazz>는 상한 제한 와일드카드(Upper Bounded Wildcard) 표현식이다. 구체적인 타입 T를 정의하지 않고, clazz의 하위 타입이기만 하면 무엇이든 매개변수로 받겠다는 다형성 위주의 선언이다. 구체적인 타입을 알 수 없으므로 읽기 전용에 가깝게 동작한다.

### 5. 와일드카드를 활용한 공변(Covariant)과 반공변(Contravariant) 지원

* 무공변의 한계를 극복하고 타입 지정의 유연성을 확보하기 위해, 와일드카드와 extends, super 키워드를 도입하여 공변과 반공변을 지원한다.
* 공변(Covariant): S가 T의 하위(상속) 관계일 때 \<? extends T>를 적용한다. 이는 하위 타입의 읽기 연산을 허용하는 구조다.
* 반공변(Contravariant): S가 T의 하위(상속) 관계일 때 \<? super S>를 적용한다. 이는 상위 타입의 쓰기 연산을 허용하는 구조다.
  * ```
    public void produce(List<? extends Animal> animals) { 
        // animals가 생산자 역할을 수행함 
        for (Animal a: animals) { System.out.println(a); } 
    } 

    public void consume (List<? super Cat> cats) { 
        // cats가 소비자 역할을 수행함 
        cats.add(new Cat()); 
    }
    ```

### 6. PECS(Producer Extends Consumer Super) 원칙의 본질

* 제너릭의 유연성을 극대화하기 위한 대원칙으로, Producer Extends Consumer Super의 앞 글자를 딴 개념이다.
* 상위 및 하위 클래스의 개념을 적용하여 객체를 생산(인스턴스를 읽어 오거나 제공)할 때는 Extends를 활용한다.
* 반대로 객체를 소비(인스턴스를 입력하거나 추가)할 때는 Super를 활용한다.
* 컬렉션 내부 요소의 추가는 부모 클래스까지 포함하여 안전하게 이루어질 수 있으므로 list.add(1) 등과 같은 소비 동작 시 super 명세가 필연적으로 수반된다.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://leehyokyun.gitbook.io/openbook/1-8.-java.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
