본문 바로가기
Java Study

와일드카드의 종류 (insert 되는지 안되는지 is-a관계)

by xogns93 2024. 7. 17.

무제한 와일드카드(Unbounded Wildcards)

 

무제한 와일드카드(Unbounded Wildcard)는 <?> 형식을 사용하여 특정 타입에 구애받지 않는 모든 참조 타입(기본타입제외란 뜻)을 나타냅니다. 이는 주로 제네릭 메서드나 클래스에서 타입을 일반화하여 사용할 때 유용합니다. 무제한 와일드카드는 컬렉션에서 읽기 작업은 가능하지만, 타입 안전성을 보장할 수 없기 때문에 삽입 작업은 제한됩니다. 

 

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

public class UnboundedWildcardExample {

    // 무제한 와일드카드를 사용하는 메서드
    public static void printList(List<?> list) {
        for (Object elem : list) {
            System.out.println(elem);
        }
    }

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

        List<Integer> intList = new ArrayList<>();
        intList.add(1);
        intList.add(2);
        intList.add(3);

        // 무제한 와일드카드를 사용하여 리스트 출력
        printList(stringList);
        printList(intList);

        // 무제한 와일드카드 리스트에 요소 삽입 시도 (컴파일 오류)
        // list.add("Orange"); // 오류 발생
    }
}

 

public static void printList(List<?> list) {
    for (Object elem : list) {
        System.out.println(elem);
    }
}

무제한 와일드카드 메서드 정의:

  • List<?>는 불특정 타입의 요소를 가진 리스트를 의미합니다.
  • 메서드 내에서 리스트의 요소를 읽을 수 있지만, 삽입할 수는 없습니다.

 

List<String> stringList = new ArrayList<>();
stringList.add("Apple");
stringList.add("Banana");
stringList.add("Cherry");

List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
intList.add(3);

// 무제한 와일드카드를 사용하여 리스트 출력
printList(stringList);
printList(intList);

메서드 호출:

무제한 와일드카드에서 삽입이 안 되는 이유

무제한 와일드카드를 사용하는 리스트에 요소를 삽입할 수 없는 이유는 타입 안전성을 보장할 수 없기 때문입니다. List<?>는 어떤 타입의 리스트인지 정확히 알 수 없으므로, 삽입할 타입을 확정할 수 없습니다.

 

List<?> list = new ArrayList<String>();
list.add("Hello"); // 컴파일 오류: 안전하지 않음

예를 들어, 다음과 같은 상황을 생각해볼 수 있습니다:

  • list는 String 타입의 리스트일 수 있지만, List<?>로 선언되어 있어 어떤 타입의 리스트인지 알 수 없습니다.
  • 따라서 "Hello" (String 타입)를 삽입하려 하면 타입 불일치가 발생할 수 있습니다.

 

요약

  • 무제한 와일드카드 (<?>): 불특정 타입의 요소를 나타내며, 모든 타입을 허용합니다.
  • 읽기 전용: 무제한 와일드카드는 주로 컬렉션에서 요소를 읽을 때 사용됩니다.
  • 삽입 불가: 타입 안전성을 보장할 수 없기 때문에 무제한 와일드카드를 사용하는 컬렉션에 요소를 삽입할 수 없습니다.

 


상한 와일드카드(Upper Bounded Wildcard)

 

상한 와일드카드(Upper Bounded Wildcard)는 <? extends T> 형식을 사용하여 특정 타입의 하위 타입들을 허용합니다. 이는 컬렉션에서 요소를 읽는 데 유용하지만, 요소를 삽입하는 데는 적합하지 않습니다. 상한 와일드카드를 사용하는 컬렉션에 요소를 삽입할 수 없는 이유는 타입 안전성을 보장하기 위해서입니다.

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

public class UpperBoundedWildcardExample {

    // 상한 와일드카드를 사용하는 메서드
    public static void processNumbers(List<? extends Number> list) {
        for (Number number : list) {
            System.out.println(number);
        }
    }

    public static void main(String[] args) {
        List<Integer> intList = new ArrayList<>();
        intList.add(1);
        intList.add(2);
        intList.add(3);

        List<Double> doubleList = new ArrayList<>();
        doubleList.add(1.1);
        doubleList.add(2.2);
        doubleList.add(3.3);

        // 상한 와일드카드를 사용하여 리스트 처리
        processNumbers(intList);
        processNumbers(doubleList);

        // 상한 와일드카드 리스트에 요소 삽입 시도 (컴파일 오류)
        // list.add(4); // 오류 발생
    }
}

 

public static void processNumbers(List<? extends Number> list) {
    for (Number number : list) {
        System.out.println(number);
    }
}

상한 와일드카드 메서드 정의 :

  • List<? extends Number>는 Number 타입 또는 그 하위 타입의 리스트를 의미합니다.
  • 리스트에서 요소를 읽을 때는 안전합니다. 모든 요소는 Number 타입이므로 Number 타입으로 처리할 수 있습니다.

 

List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
intList.add(3);

List<Double> doubleList = new ArrayList<>();
doubleList.add(1.1);
doubleList.add(2.2);
doubleList.add(3.3);

// 상한 와일드카드를 사용하여 리스트 처리
processNumbers(intList);
processNumbers(doubleList);

메서드 호출 :

상한 와일드카드에서 삽입이 안 되는 이유

상한 와일드카드를 사용하는 리스트에 요소를 삽입할 수 없는 이유는 컴파일러가 타입 안전성을 보장할 수 없기 때문입니다. 

List<? extends Number>는 Number의 하위 타입을 포함할 수 있습니다. 하지만 구체적으로 어떤 타입인지 알 수 없으므로, 안전하게 삽입할 수 있는 타입을 알 수 없습니다.

 

 

List<? extends Number> numberList = new ArrayList<Integer>();
numberList.add(1.5); // 컴파일 오류: 안전하지 않음

예를 들어, 다음과 같은 상황을 생각해볼 수 있습니다:

  • numberList는 Integer 타입의 리스트일 수 있지만, 상한 와일드카드로 선언되어 있어 Double 또는 Float 등의 다른 하위 타입일 수도 있습니다.
  • 따라서 1.5 (double 타입)를 삽입하려 하면 타입 불일치가 발생할 수 있습니다.

 

요약

  • 상한 와일드카드 (<? extends T>): T 타입 또는 그 하위 타입을 허용합니다.
  • 삽입 불가: 타입 안전성을 보장할 수 없기 때문에 상한 와일드카드를 사용하는 컬렉션에 요소를 삽입할 수 없습니다.
  • 읽기 전용: 상한 와일드카드는 주로 컬렉션에서 요소를 읽을 때 사용됩니다.

상한 와일드카드는 특정 타입의 하위 타입들을 처리할 때 유용하지만, 타입 안전성을 위해 요소 삽입은 제한됩니다.

 

 

 


 

하한 와일드카드(lower bounded wildcard)

 

하한 와일드카드(lower bounded wildcard)는 <? super T> 형식을 사용하여 특정 타입 이상의 모든 타입을 허용합니다. 이는 삽입(insertion) 작업에서 유용합니다. 하한 와일드카드를 사용하면, 해당 타입 또는 그 상위 타입의 요소들을 컬렉션에 삽입할 수 있습니다.

 

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

public class LowerBoundedWildcardExample {

    // 하한 와일드카드를 사용하는 메서드
    public static void addNumbers(List<? super Integer> list) {
        for (int i = 1; i <= 5; i++) {
            list.add(i); // Integer 타입의 요소 삽입
        }
    }

    public static void main(String[] args) {
        List<Number> numberList = new ArrayList<>();
        addNumbers(numberList);
        System.out.println(numberList); // 출력: [1, 2, 3, 4, 5]

        List<Object> objectList = new ArrayList<>();
        addNumbers(objectList);
        System.out.println(objectList); // 출력: [1, 2, 3, 4, 5]
    }
}

 

 

public static void addNumbers(List<? super Integer> list) {
    for (int i = 1; i <= 5; i++) {
        list.add(i); // Integer 타입의 요소 삽입
    }
}

하한 와일드카드 메서드 정의

  • List<? super Integer>는 Integer 타입 또는 그 상위 타입의 요소를 허용하는 리스트를 의미합니다.
  • 따라서 Integer, Number, Object 타입의 리스트에 Integer 타입의 요소를 삽입할 수 있습니다.

 

List<Number> numberList = new ArrayList<>();
addNumbers(numberList);
System.out.println(numberList); // 출력: [1, 2, 3, 4, 5]

List<Object> objectList = new ArrayList<>();
addNumbers(objectList);
System.out.println(objectList); // 출력: [1, 2, 3, 4, 5]

메서드 호출

  • numberList와 objectList는 각각 Number와 Object 타입의 리스트입니다.
  • addNumbers 메서드는 numberList와 objectList에 Integer 요소들을 삽입할 수 있습니다.

 

요약

  • 하한 와일드카드 (<? super T>): T 타입 또는 그 상위 타입을 허용합니다.
  • 삽입 가능: 하한 와일드카드를 사용하면 해당 타입 또는 그 상위 타입의 요소를 컬렉션에 삽입할 수 있습니다.
  • is-a 관계: 하한 와일드카드는 상위 타입과의 is-a 관계를 활용하여 요소 삽입을 가능하게 합니다.

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

public class WildcardExample {
    public static void main(String[] args) {
        List<?> wildcardList = new ArrayList<Integer>();

        // null 삽입은 허용됩니다.
        wildcardList.add(null);

        // 다른 객체 삽입 시도 (컴파일 오류 발생)
        // wildcardList.add("Hello");  // 컴파일 오류
        // wildcardList.add(123);      // 컴파일 오류

        System.out.println("List contains: " + wildcardList);
    }
}

 

List는 동일한 데이터 타입의 엘리먼트여야 하는데 <?> 는 알 수 없는 타입의 List 이기 때문에

null은 아무것도 참조안한단 거라서 삽입 가능하다.

 

 

 

'Java Study' 카테고리의 다른 글

Type Erasure(타입 소거)  (0) 2024.07.18
@ 어노테이션 (Annotation)  (0) 2024.07.18
자바 ArrayList 특징 & 사용법 정리  (5) 2024.07.16
동일성(Identity)과 동등성(Equality)  (0) 2024.07.16
캐시(Cache)와 캐싱(Caching)  (0) 2024.07.16