λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

빈 ꡬ멍 μ±„μš°κΈ°

[Java] μ œλ„€λ¦­κ³Ό μ™€μΌλ“œμΉ΄λ“œ

좜처

ChatGPT


μ œλ„€λ¦­ Generics

κ°œμš”

μ œλ„€λ¦­μ€ 클래슀 μΈν„°νŽ˜μ΄μŠ€, λ©”μ„œλ“œμ—μ„œ μ‚¬μš©ν•  데이터 νƒ€μž…μ„ μΌλ°˜ν™”ν•˜μ—¬ μ„ μ–Έ μ‹œμ μ— ꡬ체적인 νƒ€μž…μ„ 지정할 수 μžˆλ„λ‘ ν•˜λŠ” μžλ°”μ˜ κΈ°λŠ₯. μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λ©΄ μ»΄νŒŒμΌλŸ¬κ°€ νƒ€μž…μ„ μ²΄ν¬ν•˜λ―ˆλ‘œ, 잘λͺ»λœ νƒ€μž…μ„ μ‚¬μš©ν•˜λŠ” 였λ₯˜λ₯Ό 쀄이고 νƒ€μž… μ•ˆμ „μ„±μ„ 높일 수 μžˆλ‹€.

μž₯점

1. νƒ€μž… μ•ˆμ •μ„± Type Safety

μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λ©΄ 컴파일 μ‹œμ μ— νƒ€μž… 체크가 이루어져 잘λͺ»λœ νƒ€μž…μ΄ λ“€μ–΄κ°€λŠ” 것을 방지할 수 μžˆλ‹€.

2. μ½”λ“œ μž¬μ‚¬μš©μ„±

ν•˜λ‚˜μ˜ ν΄λž˜μŠ€λ‚˜ λ©”μ„œλ“œλ‘œ λ‹€μ–‘ν•œ 데이터 νƒ€μž…μ„ μ²˜λ¦¬ν•  수 μžˆμ–΄ μ½”λ“œ 쀑볡을 쀄일 수 μžˆλ‹€.

3. λͺ…ν™•ν•œ μ½”λ“œ

νƒ€μž… μΊμŠ€νŒ…μ΄ λΆˆν•„μš”ν•΄μ Έμ„œ μ½”λ“œκ°€ κ°„κ²°ν•˜κ³  읽기 μ‰¬μ›Œμ§„λ‹€.

κΈ°λ³Έ 문법

// μ œλ„€λ¦­ 클래슀 μ„ μ–Έ
public class Box<T> {
    private T item;

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

    public T getItem() {
        return item;
    }
}

// μ œλ„€λ¦­ μ‚¬μš© μ˜ˆμ‹œ
Box<String> stringBox = new Box<>();
stringBox.setItem("Hello");
String message = stringBox.getItem(); // μΊμŠ€νŒ… λΆˆν•„μš”

 

μ œλ„€λ¦­ λ©”μ„œλ“œ

μ œλ„€λ¦­ λ©”μ„œλ“œλŠ” λ©”μ„œλ“œ λ ˆλ²¨μ—μ„œ νƒ€μž…μ„ λ§€κ°œλ³€μˆ˜λ‘œ μ‚¬μš©ν•˜λŠ” 방법. λ©”μ„œλ“œκ°€ 호좜될 λ•Œ νƒ€μž…μ΄ κ²°μ •λœλ‹€.

// μ œλ„€λ¦­ λ©”μ„œλ“œ μ„ μ–Έ
public <T> void printArray(T[] array) {
    for (T element : array) {
        System.out.println(element);
    }
}

// μ œλ„€λ¦­ λ©”μ„œλ“œ μ‚¬μš© μ˜ˆμ‹œ
Integer[] intArray = {1, 2, 3};
String[] strArray = {"A", "B", "C"};

printArray(intArray); // Integer 배열을 좜λ ₯
printArray(strArray); // String 배열을 좜λ ₯

// μ œλ„€λ¦­ λ©”μ„œλ“œ μ„ μ–Έ
public <T> void printArray(T[] array) {
    for (T element : array) {
        System.out.println(element);
    }
}

// μ œλ„€λ¦­ λ©”μ„œλ“œ μ‚¬μš© μ˜ˆμ‹œ
Integer[] intArray = {1, 2, 3};
String[] strArray = {"A", "B", "C"};

printArray(intArray); // Integer λ°°μ—΄μ„ μΆœλ ₯
printArray(strArray); // String λ°°μ—΄μ„ μΆœλ ₯

 

μ™€μΌλ“œ μΉ΄λ“œ Wildcards

κ°œμš”

μ™€μΌλ“œμΉ΄λ“œλŠ” μ œλ„€λ¦­ νƒ€μž…μ˜ 경계λ₯Ό μ •μ˜ν•˜λŠ” 데 μ‚¬μš©λ˜λ©°, μ œλ„€λ¦­ ν΄λž˜μŠ€λ‚˜ λ©”μ„œλ“œκ°€ λ‹€λ£° 수 μžˆλŠ” νƒ€μž…μ˜ λ²”μœ„λ₯Ό ν™•μž₯ν•˜κ±°λ‚˜ μ œν•œν•œλ‹€. 주둜 λΆˆνŠΉμ •ν•œ νƒ€μž…μ„ μ²˜λ¦¬ν•  λ•Œ μ‚¬μš©λœλ‹€.

μ™€μΌλ“œμΉ΄λ“œμ˜ μ’…λ₯˜

1. μ–Έλ°”μš΄λ“œ μ™€μΌλ“œ μΉ΄λ“œ '?'

  • '<?>'λŠ” νŠΉμ • νƒ€μž…μ— μ œν•œμ΄ μ—†λŠ” κ²½μš°μ— μ‚¬μš©λœλ‹€.
  • 읽기 μ „μš©: μ™€μΌλ“œμΉ΄λ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μ»¬λ ‰μ…˜μ— 데이터λ₯Ό μΆ”κ°€ν•˜λŠ” 것이 μ œν•œλ  수 μžˆλ‹€.

2. μƒν•œ 경계 μ™€μΌλ“œμΉ΄λ“œ '? extends T'

  • '<? extends T>'λŠ” μ™€μΌλ“œμΉ΄λ“œ νƒ€μž…μ΄ T 클래슀의 μ„œλΈŒν΄λž˜μŠ€μ΄κ±°λ‚˜ T 자체λ₯Ό 가리킨닀.
  • 읽기 μ „μš© : μ»¬λ ‰μ…˜μ—μ„œ 데이터λ₯Ό 읽을 수 μžˆμ§€λ§Œ, μΆ”κ°€ν•˜λŠ” 것은 μ œν•œλœλ‹€.

3. ν•˜ν•œ 경계 μ™€μΌλ“œμΉ΄λ“œ '? super T'

  • '<? super T>'λŠ” μ™€μΌλ“œμΉ΄λ“œ νƒ€μž…μ΄ T 클래슀의 μŠˆνΌν΄λž˜μŠ€μ΄κ±°λ‚˜ T 자체λ₯Ό 가리킨닀.
  • μ“°κΈ° κ°€λŠ₯ : μ»¬λ ‰μ…˜μ΄ 데이터λ₯Ό μΆ”κ°€ν•  수 μžˆλ‹€.

μ‚¬μš© μ˜ˆμ‹œ

import java.util.List;

public class WildcardExample {

    // μ–Έλ°”μš΄λ“œ μ™€μΌλ“œμΉ΄λ“œ μ‚¬μš©
    public static void printList(List<?> list) {
        for (Object element : list) {
            System.out.println(element);
        }
    }

    // μƒν•œ 경계 μ™€μΌλ“œμΉ΄λ“œ μ‚¬μš©
    public static double sumNumbers(List<? extends Number> list) {
        double sum = 0;
        for (Number number : list) {
            sum += number.doubleValue();
        }
        return sum;
    }

    // ν•˜ν•œ 경계 μ™€μΌλ“œμΉ΄λ“œ μ‚¬μš©
    public static void addNumbers(List<? super Integer> list) {
        list.add(10);
        list.add(20);
    }
}

 

μ‚¬μš© μ˜ˆμ‹œ μ„€λͺ…

  • μ–Έλ°”μš΄λ“œ μ™€μΌλ“œμΉ΄λ“œ : 'printList' λ©”μ„œλ“œλŠ” λͺ¨λ“  νƒ€μž…μ˜ 리슀트λ₯Ό λ°›μ•„ 좜λ ₯ν•œλ‹€.
List<String> stringList = Arrays.asList("A", "B", "C");
WildcardExample.printList(stringList);
  • μƒν•œ 경계 μ™€μΌλ“œμΉ΄λ“œ : 'sumNumbers' λ©”μ„œλ“œλŠ” 'Number'의 ν•˜μœ„ 클래슀(예: 'Integer', 'Double')의 리슀트λ₯Ό λ°›μ•„ 합계λ₯Ό κ³„μ‚°ν•œλ‹€.
List<Integer> intList = Arrays.asList(1, 2, 3);
double sum = WildcardExample.sumNumbers(intList);
System.out.println("Sum: " + sum);

 

  • ν•˜ν•œ 경계 μ™€μΌλ“œμΉ΄λ“œ : 'addNumbers' λ©”μ„œλ“œλŠ” 'Integer'의 슈퍼클래슀(예: 'Number', 'Object')의 λ¦¬μŠ€νŠΈμ— 값을 μΆ”κ°€ν•œλ‹€.
List<Number> numberList = new ArrayList<>();
WildcardExample.addNumbers(numberList);
System.out.println(numberList); // [10, 20]

 

μ œλ„€λ¦­κ³Ό μ™€μΌλ“œμΉ΄λ“œμ˜ 차이점

νŠΉμ§• μ œλ„€λ¦­ μ™€μΌλ“œμΉ΄λ“œ
νƒ€μž… μ •μ˜ λͺ…ν™•ν•œ νƒ€μž…μ„ μ„ μ–Έν•˜λ©°, νŠΉμ • νƒ€μž…μœΌλ‘œ μ œν•œν•œλ‹€. νŠΉμ • νƒ€μž…μ˜ 경계λ₯Ό μœ μ—°ν•˜κ²Œ 지정할 수 μžˆλ‹€.
μœ ν˜• <T>: νŠΉμ • νƒ€μž…μ„ λͺ…μ‹œμ μœΌλ‘œ μ •μ˜ <?> : λΆˆνŠΉμ • νƒ€μž…
<? extends T> μƒν•œ 경계
<? super T> : ν•˜ν•œ 경계
μ‚¬μš© λͺ©μ  νƒ€μž…μ„ λͺ…ν™•ν•˜κ²Œ μ •μ˜ν•˜μ—¬ μ½”λ“œμ˜ μ•ˆμ •μ„±μ„ 높인닀. μ—¬λŸ¬ νƒ€μž…μ„ ν˜€μš©ν•˜κ±°λ‚˜ νƒ€μž…μ˜ λ²”μœ„λ₯Ό ν™•μž₯ν•  λ•Œ μ‚¬μš©ν•œλ‹€.
μœ μ—°μ„± 덜 μœ μ—°ν•˜λ‹€. ꡬ체적인 νƒ€μž…μ„ 미리 μ •μ˜ν•΄μ•Ό ν•œλ‹€. 더 μœ μ—°ν•˜λ‹€. λ‹€μ–‘ν•œ νƒ€μž…μ„ μˆ˜μš©ν•  수 μžˆλ‹€.
읽기/μ“°κΈ° μ œλ„€λ¦­ νƒ€μž…μ— 따라 읽기와 μ“°κΈ°κ°€ λͺ¨λ‘ κ°€λŠ₯ν•˜λ‹€ μ™€μΌλ“œμΉ΄λ“œμ— 따라 읽기와 μ“°κΈ°κ°€ μ œν•œλ  수 μžˆλ‹€.

 

μ‹€μš©μ μΈ μ‚¬μš© 예

μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λŠ” 이유

μ œλ„€λ¦­μ€ κ°•λ ₯ν•œ νƒ€μž… 체크와 μ½”λ“œμ˜ λͺ…확성을 μ œκ³΅ν•œλ‹€. 예λ₯Ό λ“€μ–΄, 리슀트의 λͺ¨λ“  μš”μ†Œκ°€ νŠΉμ • νƒ€μž…μž„μ„ 보μž₯ν•  수 μžˆλ‹€.

List<String> strings = new ArrayList<>();
strings.add("Hello");
strings.add("World");

// νƒ€μž… 뢈일치 였λ₯˜ 방지
// strings.add(10); // 컴파일 였λ₯˜ λ°œμƒ

 

μ™€μΌλ“œμΉ΄λ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 이유

μ™€μΌλ“œμΉ΄λ“œλŠ” λ‹€μ–‘ν•œ νƒ€μž…μ„ μˆ˜μš©ν•  λ•Œ μœ μš©ν•˜λ‹€. 예λ₯Ό λ“€μ–΄, λ‹€ν˜•μ„±μ„ μ§€μ›ν•˜λŠ” λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•  λ•Œ μ‚¬μš©λœλ‹€.

public static void printCollection(Collection<?> collection) {
    for (Object element : collection) {
        System.out.println(element);
    }
}

List<Integer> integers = Arrays.asList(1, 2, 3);
List<String> strings = Arrays.asList("A", "B", "C");

printCollection(integers);
printCollection(strings);

 

μƒν•œ 경계 μ™€μΌλ“œμΉ΄λ“œμ™€ ν•˜ν•œ 경계 μ™€μΌλ“œμΉ΄λ“œμ˜ ν™œμš©

  • μƒν•œ 경계 : λΆˆλ³€μ˜ κ²½μš°μ— μ‚¬μš©ν•˜μ—¬ 읽기 μ „μš©μœΌλ‘œ 데이터λ₯Ό μ²˜λ¦¬ν•œλ‹€.
public static void processNumbers(List<? extends Number> numbers) {
    for (Number num : numbers) {
        System.out.println(num);
    }
}

List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);
processNumbers(doubles); // Double νƒ€μž…λ„ ν—ˆμš©
  • ν•˜ν•œ 경계 : κ°€λ³€μ˜ κ²½μš°μ— μ‚¬μš©ν•˜μ—¬ μ•ˆμ „ν•˜κ²Œ 데이터λ₯Ό μΆ”κ°€ν•  수 μžˆλ‹€.
public static void addIntegers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
}

List<Number> numbers = new ArrayList<>();
addIntegers(numbers);
System.out.println(numbers); // [1, 2]

 

μ œλ„€λ¦­κ³Ό μ™€μΌλ“œμΉ΄λ“œμ˜ μ œμ•½ 사항

1. μ œλ„€λ¦­ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€ν™”

μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ 직접 μΈμŠ€ν„΄μŠ€ν™”ν•  수 μ—†λ‹€. 예λ₯Ό λ“€μ–΄, 'T obj = new T();' λŠ” ν—ˆμš©λ˜μ§€ μ•ŠλŠ”λ‹€.

2. κΈ°λ³Έ νƒ€μž… μ‚¬μš© λΆˆκ°€

μ œλ„€λ¦­μ€ κΈ°λ³Έ 데이터 νƒ€μž…('int', 'char', 'double' λ“±)을 μ‚¬μš©ν•  수 μ—†λ‹€. λŒ€μ‹ , 래퍼 클래슀('Integer', 'Character', 'Double'λ“±)λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

3. μŠ€νƒœν‹± μ»¨ν…μŠ€νŠΈμ—μ„œμ˜ μ œλ„€λ¦­ μ‚¬μš©

μ œλ„€λ¦­ νƒ€μž…μ€ μŠ€νƒœν‹± μ»¨ν…μŠ€νŠΈμ—μ„œ μ‚¬μš©λ  수 μ—†λ‹€. μŠ€νƒœν‹± ν•„λ“œλ‚˜ λ©”μ„œλ“œμ—μ„œ μ œλ„€λ¦­ νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

4. μžλ°” νƒ€μž… μ†Œκ±° Type Erasure

μžλ°”μ˜ μ œλ„€λ¦­μ€ 컴파일 νƒ€μž„μ— νƒœμž… 체크λ₯Ό μˆ˜ν–‰ν•˜κ³ , λŸ°νƒ€μž„μ—λŠ” νƒ€μž… 정보가 μ œκ±°λœλ‹€. μ΄λŠ” 일뢀 μƒν™©μ—μ„œ νƒ€μž… μΊμŠ€νŒ… 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆλ‹€.

5. λ°°μ—΄κ³Ό μ œλ„€λ¦­

μ œλ„€λ¦­ νƒ€μž…μ˜ 배열을 생성할 수 μ—†λ‹€. 예λ₯Ό λ“€μ–΄, 'T[] array = new T[10];'λŠ” ν˜€μš©λ˜μ§€ μ•ŠλŠ”λ‹€.

6. μƒν•œ 경계 μ™€μΌλ“œμΉ΄λ“œμ™€ λ©”μ„œλ“œ μ˜€λ²„λ‘œλ”©μ˜ μ œν•œ

μ™€μΌλ“œμΉ΄λ“œλ₯Ό μ‚¬μš©ν•œ λ©”μ„œλ“œ μ˜€λ²„λ‘œλ”©μ€ ν˜Όλž€μ„ μ΄ˆλž˜ν•  수 μžˆμœΌλ―€λ‘œ ν”Όν•΄μ•Ό ν•œλ‹€.

public void doSomething(List<? extends Number> list) { ... }
public void doSomething(List<Integer> list) { ... } // λͺ¨ν˜Έν•œ 호좜 λ°œμƒ κ°€λŠ₯

 

κ²°λ‘ 

μ œλ„€λ¦­κ³Ό μ™€μΌλ“œμΉ΄λ“œλŠ” μžλ°”μ˜ νƒ€μž… μ•ˆμ •μ„±μ„ 보μž₯ν•˜κ³  μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±μ„ λ†’μ΄λŠ” μ€‘μš”ν•œ 도ꡬ이닀. μ œλ„€λ¦­μ€ νƒ€μž…μ„ λͺ…ν™•ν•˜κ²Œ μ •μ˜ν•˜μ—¬ νƒ€μž… μ•ˆμ „μ„±μ„ 높이고, μ™€μΌλ“œμΉ΄λ“œλŠ” μœ μ—°μ„±μ„ μ œκ³΅ν•˜μ—¬ λ‹€μ–‘ν•œ νƒ€μž…μ„ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ ν•œλ‹€. μ œλ„€λ¦­κ³Ό μ™€μΌλ“œμΉ΄λ“œμ˜ μ΄ν•΄λŠ” μžλ°” ν”„λ‘œκ·Έλž˜λ°μ—μ„œ μ•ˆμ „ν•˜κ³  효율적인 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ” 데 ν•„μˆ˜μ μ΄λ‹€. 이λ₯Ό 톡해 νƒ€μž… 였λ₯˜λ₯Ό 사전에 λ°©μ§€ν•˜κ³ , 보닀 읽기 쉽고 μœ μ§€λ³΄μˆ˜ν•˜κΈ° μ‰¬μš΄ μ½”λ“œλ₯Ό μž‘μ„±ν•  수 μžˆλ‹€.