티스토리 뷰

Java

[Java] Generic

snail voyager 2025. 3. 3. 00:01
728x90
반응형
Java에서 데이터 타입을 일반화하여 다양한 타입을 하나의 코드로 처리할 수 있도록 해주는 기능
컴파일 시 타입을 체크하면서도, 다양한 데이터 타입을 유연하게 사용할 수 있도록
도와줍니다.

제네릭 사용 방법

import java.util.ArrayList;

public class WithGeneric {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>(); // 타입 지정
        list.add("Hello");
        // list.add(123); // 컴파일 오류 발생 (잘못된 타입)

        String str = list.get(0); // 형 변환 필요 없음
        System.out.println(str);
    }
}
  • 타입 안정성(type safety): 잘못된 타입을 넣으면 컴파일 시점에서 오류가 발생
  • 형 변환 불필요: Object → 원하는 타입으로 변환할 필요 없음

제네릭 클래스 만들기

class Box<T> {
    private T value;

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

    public T get() {
        return value;
    }
}

public class GenericExample {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.set("Hello");
        System.out.println(stringBox.get());

        Box<Integer> intBox = new Box<>();
        intBox.set(100);
        System.out.println(intBox.get());
    }
}
  • T는 타입 매개변수(Type Parameter)로, 사용자가 원하는 타입으로 변경할 수 있음

제네릭 메서드 만들기

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

public class GenericMethod {
    public static void main(String[] args) {
        Utils.print("Hello");
        Utils.print(100);
        Utils.print(3.14);
    }
}
  • <T>를 메서드 앞에 선언하면, 해당 메서드에서 제네릭을 사용할 수 있음

와일드카드 (? 기호)

import java.util.ArrayList;
import java.util.List;

class Printer {
    public static void printList(List<?> list) { // 와일드카드 사용
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
}

public class WildcardExample {
    public static void main(String[] args) {
        List<String> strList = new ArrayList<>();
        strList.add("Apple");
        strList.add("Banana");

        List<Integer> intList = new ArrayList<>();
        intList.add(10);
        intList.add(20);

        Printer.printList(strList);
        Printer.printList(intList);
    }
}
  • List<?> → 어떤 타입이든 받을 수 있는 리스트
List<?> list = new ArrayList<>();
list.add(1);	//추가 불가능
  • 와일드카드는 unknown type 이므로 컴파일러가 어떤 타입인지 추론할 수 없음
  • 요소를 추가하는 연산은 허용하지 않는다.

제네릭의 제한 (Bounded Type)

class Calculator<T extends Number> { // Number 또는 그 하위 클래스만 허용
    private T num;

    public Calculator(T num) {
        this.num = num;
    }

    public double square() {
        return num.doubleValue() * num.doubleValue();
    }
}

public class BoundedTypeExample {
    public static void main(String[] args) {
        Calculator<Integer> intCalc = new Calculator<>(10);
        Calculator<Double> doubleCalc = new Calculator<>(5.5);
        // Calculator<String> stringCalc = new Calculator<>("Hello"); // 컴파일 오류 발생
        
        System.out.println(intCalc.square());
        System.out.println(doubleCalc.square());
    }
}
  • <T extends Number> → T는 Number 클래스 또는 그 하위 클래스(Integer, Double 등)만 가능
  • String 같은 타입은 사용할 수 없음

제네릭 인터페이스

interface Data<T> {
    void setData(T data);
    T getData();
}

class StringData implements Data<String> {
    private String data;

    @Override
    public void setData(String data) {
        this.data = data;
    }

    @Override
    public String getData() {
        return data;
    }
}

public class GenericInterfaceExample {
    public static void main(String[] args) {
        StringData stringData = new StringData();
        stringData.setData("Hello");
        System.out.println(stringData.getData());
    }
}

제네릭 배열 (주의점)

class GenericArray<T> {
    private T[] arr;

    public GenericArray(int size) {
        // arr = new T[size];  // ❌ 컴파일 오류 발생
        arr = (T[]) new Object[size];  // ✅ 이렇게 해결
    }

    public void set(int index, T value) {
        arr[index] = value;
    }

    public T get(int index) {
        return arr[index];
    }
}

public class GenericArrayExample {
    public static void main(String[] args) {
        GenericArray<String> stringArray = new GenericArray<>(5);
        stringArray.set(0, "Hello");
        System.out.println(stringArray.get(0));
    }
}
  • Java에서는 제네릭 배열을 직접 생성할 수 없습니다.
  • new Object[size]을 생성한 후 (T[])로 형 변환

 

728x90
반응형

'Java' 카테고리의 다른 글

[Java] DIP (Dependency Inversion Principle)  (0) 2025.03.03
[Java] Bounded WildCard  (1) 2025.03.03
[Java] try-with-resources  (0) 2025.03.01
[Java] JSON Jackson @JsonProperty  (0) 2025.02.24
[Java] OpenCSV  (0) 2025.01.26
반응형
300x250