본문 바로가기
Java

자바 중급 2편 - 제네릭(1)

by KongJiHoon 2025. 5. 11.

1. 제네릭이란?

  • 제네릭(Generic)은 클래스 내부에서 사용할 타입을 외부에서 지정할 수 있게 하는 문법.
  • 코드 재사용성과 타입 안정성을 동시에 제공하는 자바의 핵심 기능.

 

2. 제네릭의 필요성

 

 

(1) 문제 상황 1: 타입별 클래스를 반복 구현해야 함

public class IntegerBox { private Integer value; }
public class StringBox { private String value; }
  • IntegerBox, StringBox처럼 타입마다 클래스 생성 → 유지보수 어렵고 비효율적

 

(2) 문제 상황 2: Object 사용시 다운 캐스팅 필요

package com.example.generic.ex1;

public class ObjectBox {

    private Object value;

    public void set(Object value) {
        this.value = value;
    }

    public Object get() {
        return value;
    }
}

 

package com.example.generic.ex1;

public class BoxMain2 {


    public static void main(String[] args) {

        ObjectBox integerBox = new ObjectBox();
        integerBox.set(1);

        Integer integer = (Integer) integerBox.get(); // Object -> Integer 다운 캐스팅

        System.out.println("integer = " + integer);

        ObjectBox stringBox = new ObjectBox();
        stringBox.set("hello");
        String string = (String) stringBox.get();// Object -> String 다운 캐스팅
        System.out.println("string = " + string);

        // 잘못된 타입의 인수 전달시
        integerBox.set("문자100");
        Integer result = (Integer) integerBox.get();

        // ClassCastException 발생
        System.out.println("result = " + result);
    }
}
  • 모든 타입을 Object로 받고 꺼낼 때 강제 형변환(casting) 필요 → 타입 안정성 떨어짐

 

(3) 제네릭(Generic)

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

 

GenericBox<Integer> intBox = new GenericBox<>();
intBox.set(10);
Integer result = intBox.get(); // ✅ 안전, 캐스팅 불필요

 

  • T는 타입 매개변수, 사용할 때 실제 타입을 전달하여 사용.
용어 설명
Generic Type 제네릭을 사용하는 클래스/인터페이스
타입 매개변수 GenericBox<T>의 T
타입 인자 GenericBox<String>의 String
Raw Type GenericBox처럼 타입 미지정 (지양해야 함)

 

제네릭의 장점

비교 코드 재사용성 타입 안정성
일반 클래스
Object 사용
✅ 제네릭 사용

 

  • 메서드: void print(String value) → 값을 나중에 결정
  • 제네릭: class Box<T> → 타입을 나중에 결정

 

제네릭의 명명 관례

이름 의미
T Type
E Element
K Key
V Value
S, U, V 추가 타입 매개변수

 

예제 1) 다음 코드 참고 -> Container클래스 생성

package com.example.generic.test.ex1;

public class ContainerTest {

    public static void main(String[] args) {
        Container<String> stringContainer = new Container<>();

        System.out.println("빈값 확인: " + stringContainer.isEmpty());

        stringContainer.setItem("data1");
        System.out.println("저장데이터: " + stringContainer.getItem());
        System.out.println("빈값 확인2: " + stringContainer.isEmpty());

        Container<Integer> integerContainer = new Container<>();

        integerContainer.setItem(10);
        System.out.println("저장데이터: " + integerContainer.getItem());
    }
}

 

package com.example.generic.test.ex1;

public class Container<T> {

    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }

    public boolean isEmpty() {
        return item == null;
    }

}

 

 

 

예제 2) 다음 코드 참고 -> Pair 클래스 생성

package com.example.generic.test.ex2;

public class PairTest {

    public static void main(String[] args) {

        Pair<Integer, String> pair1 = new Pair<>();

        pair1.setFirst(1);
        pair1.setData("data");
        System.out.println(pair1.getFirst());
        System.out.println(pair1.getData());
        System.out.println("pair1 = " + pair1);

        Pair<String, String> pair2 = new Pair<>();
        pair2.setFirst("key");
        pair2.setData("value");
        System.out.println(pair2.getFirst());
        System.out.println(pair2.getData());
        System.out.println("pair2 = " + pair2);
    }
}

 

package com.example.generic.test.ex2;

public class Pair<K, V> {

    private K key;
    private V value;

    public void setFirst(K key) {
        this.key = key;
    }

    public void setData(V value) {
        this.value = value;
    }

    public K getFirst() {
        return key;
    }

    public V getData() {
        return value;
    }

    @Override
    public String toString() {
        return "Pair{" +
                "key=" + key +
                ", value=" + value +
                '}';
    }
}

 

 

✅ 정리

 

  • 제네릭은 타입 안정성을 유지하면서 코드 재사용성을 극대화할 수 있는 강력한 기능이다.
  • 실무에서도 List<String>, Map<K, V> 등으로 자주 사용되므로 반드시 숙지.
  • 타입 안정성 + 중복 제거 = 제네릭의 진가

 

 

'Java' 카테고리의 다른 글

자바 중급 2편 - 제네릭(3)  (0) 2025.05.31
자바 중급 2편 - 제네릭(2)  (0) 2025.05.15
Java 중급 1 - 예외처리(4)  (0) 2025.05.10
Java 중급 1 - 예외처리(3)  (0) 2025.05.05
Java 중급 1 - 예외처리(2)  (0) 2025.05.04