Spring_부캠/두고두고 볼 개념

[Java]Generics

FS29 2025. 7. 18. 13:43
 Generics

 

 

 

제네릭이란?

List<String>에서 <> 안의 String. 
자료형(타입)을 코드가 실행되기 전에 미리 고정하지 않고 외부에서 나중에 넣게끔 설계하는 문법이다.
쉽게 말하면 자료형을 직접 넣지 말고 <>로 비워두고 나중에 이건 String이야~, 이건 Integer야~ 라고 지정하게 하자.

 

왜 제네릭을 쓰는가?

타입마다 클래스를 일일이 만들면 중복이 심하고 유지보수도 어려움.  
제네릭은 하나의 클래스만 정의해두고 모든 타입에 재사용 가능하게 해준다.

→ 아래 제네릭 전/후 예시 참고.

 

public class StringBox {
    private String item;

    public void set(String item) {
        this.item = item;
    }

    public String get() {
        return item;
    }
}

위 코드와 같은 클래스가 있다고 가정해보자. 이거는 String 만 담을 수 있는 박스. 그럼 int도 담고 싶을 때 또 만들어야 하나?라는 생각을 할 수 있다.

public class IntegerBox {
    private Integer item;
    public void set(Integer item) { this.item = item; }
    public Integer get() { return item; }
}

public class DoubleBox {
    private Double item;
    public void set(Double item) { this.item = item; }
    public Double get() { return item; }
}

public class BooleanBox {
    private Boolean item;
    public void set(Boolean item) { this.item = item; }
    public Boolean get() { return item; }
}

이건 타입마다 클래스를 일일이 새로 만들어야 한다. 중복이 너무 심함.

 

그래서 이런 중복을 없애고 하나의 클래스로 모든 타입을 처리할 때 제네릭.

public class Box<T> {
    private T item;
    public void set(T item) { this.item = item; }
    public T get() { return item; }
}

따라서 제네릭은 재사용 가능한 코드를 만들기 위해 필수

 

또한 List는 내부 요소의 타입을 모르는 상태로 만들어진다. 그래서 타입 매개변수를 필요로 함.

그래서 List<T> 이런 식으로 선언되어 있고 사용 시 List<String>처럼 구체적인 타입을 만들어줘야 한다.

즉, List, Map, Set같은 컬렉션은 내부적으로 제네릭으로설계되어 있다.

 

생성된 제네릭은 아래 코드와 같이 사용하면 된다.

Box<String> strBox = new Box<>();       // StringBox 역할
Box<Integer> intBox = new Box<>();      // IntegerBox 역할
Box<Double> doubleBox = new Box<>();    // DoubleBox 역할
Box<Boolean> boolBox = new Box<>();     // BooleanBox 역할

 

제네릭의 기초 문법
class Box<T> {
    private T item;

    public void set(T item) { this.item = item; }
    public T get() { return item; }
}

 

T는 타입 매개변수(Type parameter)

클래스나 메서드가 어떤 타입을 받을지 미정인 상태로 설계 가능하다.

 

Box<String> strBox = new Box<>();
strBox.set("Hello");
String val = strBox.get(); // 형변환 없이 사용 가능!

 

제네릭 클래스 vs 제네릭 메서드

 

제네릭 클래스

class Container<T> {
    T data;
}

 

제네릭 메서드

public class Util {
    public static <T> void print(T value) {
        System.out.println(value);
    }
}

<T>가 리턴 타입 앞에 있다. 메서드 자체가 제네릭이라는 뜻이ㅏㄷ.

 

제네릭 사용 시 주의 사항
class MyClass<T> { ... }   // 제네릭 클래스
<T> void myMethod(T val)   // 제네릭 메서드
List<int> list = new ArrayList<>();  // 오류 (원시 타입 불가)
Box<String> b = new Box<>();
b.set("hi"); // ok
b.set(123);  // 오류 (String만 허용)

 

 


질문사항

 

Q1. <> 안엔 꼭 T여야 해?

=> No. 관례적으로 T를 많이 씀

 

Q2. <?>는 뭐야?

와일드카드. “모르겠지만 뭔가 타입이 있을 거야” 라는 뜻.
제한을 줄 수 있음 → <? extends Number>, <? super Integer>

 

Q3. 제네릭은 형변환 안 해도 된다고?

=>Yes, 제네릭은 컴파일 타임에 타입을 검사해줌 → 실수 예방, 가독성 향상

List names = new ArrayList(); // 제네릭 미사용
names.add("hi");
String name = (String) names.get(0); // 형변환 필요 x 위험

List<String> names = new ArrayList<>(); // 제네릭 사용
String name = names.get(0); // 형변환 필요 없음 안전

 

Q4. 제네릭 클래스 vs 제네릭 메서드 구분 맞아?

=> Yes,

제네릭 클래스

public class Box<T> {
    T item;
}

 T는 클래스 전체에 적용

제네릭 메서드

public class Util {
    public static <T> void print(T value) {
        System.out.println(value);
    }
}

→ <T>가 메서드 안에서만 사용됨. 클래스 전체는 제네릭 아님.

 

'Spring_부캠 > 두고두고 볼 개념' 카테고리의 다른 글

[Spring] HTTP & 네트워크 & Web 기초 입문 (1주차 강의 정리)  (1) 2025.07.22
[Java] Lambda & Streams  (1) 2025.07.18
[Java] enum  (2) 2025.07.17
[Java] Optinal 대체 왜 쓰는데?  (2) 2025.07.11
[Java] Quize  (1) 2025.07.11