Search

반응형

'와일드카드'에 해당되는 글 1건

  1. 2020.05.10 [자바/java]제너릭과 와일드카드 - <? Extends E> (generic/wildcards) 1
반응형

[자바/java]제너릭과 와일드카드 - <? Extends E> (generic/wildcards)

안녕하세요. 신기한 연구소 개발자 티보이입니다.

자바 개발을 하다 보면 배열, Collection 등을 사용하게 됩니다.

다양한 타입을 지원하기 위해 제너릭(generic)을 사용하는데요.

그중 와일드카드(wildcards)를 사용하는데 처음 사용하거나 또는 확실히 이해가 필요한 개발자를 위해 한 번 포스팅해봅니다.

확실히 이해하고 사용한다면 많은 도움이 될 거예요.

렛츠 고~

제너릭을 사용하는 이유는

타입을 미리 지정해서 캐스팅을 사용하지 않아 좀 더 명확하게 사용할 수 있도록 해줍니다.

제너릭(generic)을 사용한 코드를 확인해보겠습니다.

1
2
3
4
5
6
7
8
9
void printCollection(Collection<Object> c) {
 
    for (Object e : c) {
 
        System.out.println(e);
 
    }
 
}
cs

코드는 <Object>라는 타입을 지정하고 있습니다.

이렇게 <Object>로 타입을 지정하는 것을 제너릭이라고 합니다.

그런데 여기서 문제가 있습니다.

혹시 해당 코드를 모든 Collection 타입을 받기 위해 만든 거라면 오류가 발생합니다.

제너릭(generic)은 지정한 타입만 받기 때문입니다.

Object 최상위 클래스이기에 받을 있다고 잘못 이해한 코드입니다.

Collection<Object>선언하면 모든 Collection 타입 모두를 허용할 수 있다는 것이 아니라 겁니다.

와일드카드 “?” 사용해서 아직 알려지지 않은 혹은 미정의 Collection 타입이라는 의미에서 Collection<?>를 사용하면 해결됩니다.

 

1
2
3
4
5
6
7
8
9
void printCollection(Collection<?> c) {
 
    for (Object e : c) {
 
        System.out.println(e);
 
    }
 
}
cs

이렇게 사용하면 Collection 다양한 타입을 사용할 있게 됩니다.

하지만 코드도 다른 문제가 있습니다.

말했듯이 Collection<?>로 와일드카드를 사용하면 Collection 타입은 안전하게 사용할 있지만 임의의 객체를 받을 수는 없습니다.

아래의 예제를 보세요.

1
2
3
4
5
Collection<?> c = new ArrayList<String>();
 
c.add(new Object()); //임의의 객체
 
 
cs

첫 번째줄은 문제가 없습니다.

아마 객체 c를 Collection<?>로 해서 다양한 타입을 지원하고 싶은 마음에 지정한 보이는데 막상 인스턴스화 하는 부분은 ArrayList<String>으로 지정했습니다.

그래서 ArrayList 아니거나 또는 ArrayList라도 String 타입이 아니면 오류 납니다.

두 번째라인을 보면 c 타입을 Collection<?>로 했기에 new Object() 객체를 add 하면 받을 있어 보이지만 사실은 오류가 발생합니다.

오류는 String 타입으로 캐스팅하라고 나올 겁니다.

 

확실히 타입을 정해서 사용한다면 와일드카드 “?” 사용해도 무방하겠지요?

 

<? extends E>

혹시 이것을 ? 어떻게 사용하는지 궁금하시나요?

제너릭(generic)은 개발의 다양성을 위한 기능이지 않을까 생각해봅니다.

 

와일드카드 “?” 설명 했으니 아시겠죠? 지정되지 않은 객체를 받을 있다는 의미입니다.

그럼 extends E 있을까요?

E elements 약자로 보시면 됩니다. E 그대로 사용하는게 아닙니다.

Extends는 상속 의미 그대로입니다. 지정되지 않은 객체 "?" 가 E를 상속받았다는 의미예요.

 

예를 들어볼께요.

게임 개발을 하는데 유닛 추상클래스(abstract clsss Units) 있습니다.

그리고 인간(class Human extends Units),

요정(class Fairy),

오크(class Oak) 구성된 유닛들이 있습니다.

세개의 클래스는 유닛 추상클래스를 상속받습니다.

유닛들은 게임판에 객체를 생성해서 이미지로 표현해야 합니다.

게임판이라는 클래스가 있고 안에는 객체를 이미지로 만드는 메서드가 있습니다.

유닛들 인간, 요정, 오크를 모두 그려야 하는 경우 각각 메서드를 구성하고 호출하게 되면 소스도 중복되고 비효율적인 소스가 됩니다.

이런 경우 객체들을 List 담은 List 객체로 넘겨주면 되는데

문제는 List 내에 인간, 요정, 오크 다양한 타입이 존재하게 됩니다.

위에서 사용한 제너릭(generic)과 와일드카드(wildcards)로 메서드를 만들어 봤습니다.

 

1
2
3
4
5
6
7
8
9
Public void showAllUnit(List<Units> units){
 
       For (Units u: units) {
 
               u.makeImg(this);
 
          }
 
}
cs

 

이렇게 되면 위에서 말했듯 List내에서 <Units> 타입만 찾게 됩니다.

, Human, Fairy, Oak 찾을 없습니다.

이런 경우 사용할 있는 제너릭(generic)이 <? Extends E> 입니다.

 

1
2
3
4
5
Public void showAllUnit(List<extends Units> units){
 
 
 
}
cs

 

이렇게 되면 List에서 와일드카드(wildcards) ? 의 타입을 찾아야 하는데 바로 Units 클래스를 상속받은 Human, Fairy, Oak를 받을 수 있게 됩니다.

이해가 되셨나요?

이제 제너릭(generic)과 와일드카드(wildcards) 그리고 <? Extends E>사용법을 알게 되었으니 개발에 활용하시길 바랍니다.

즐 코딩하세요~

반응형