일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Android
- Django REST Android
- NDK
- mfc
- 안드로이드
- C
- C++
- Rxjava2
- RxJava
- UWP
- Django REST
- 알고리즘
- Java
- flutter firestore
- android push
- Python
- Django REST framework
- C/C++
- 프로그래머스
- Flutter TextField
- 코틀린
- android architecture component
- 안드로이드 구글맵
- Android P
- Kotlin
- dart
- RxAndroid
- kodility
- livedata
- FLUTTER
- Today
- Total
개발하는 두더지
[Effective Java 규칙28] 한정적 와일드카드를 써서 API 유연성을 높여라 본문
[Effective Java 규칙28] 한정적 와일드카드를 써서 API 유연성을 높여라
Effective Java 2/E 책과 구글링을 통해 내용을 정리하고 개인적인 견해가 포함된 글입니다.
유연성을 최대화하려면, 객체를 만드는 생산자 Producer나 객체를 사용하는 소비자 Consumer 역할을 하는 메서드 인자의 자료형은 와일드 카드 자료형으로 하면 된다. 만약 메서드 인자가 생산자이면서 소비자라면 와일드카드 자료형은 필요없다.
PECS( Producer - extends , Consumer - super ) 을 사용하면 된다.
예를들어 Collection 인자가 E 생산자라면
Collection<? extends E>
Collection인자가 E 소비자라면
Collection<? super E>
<? extends E> 는 E의 하위 자료형의 Collection이다. <E> 라고 한다면 E의 Collection이기때문에 인자로 넣을 수 있는 범위가 달라진다.
대표적인 예로 자바에는 Byte, Double, Float, Integer, Long, Short 자료형을 사용하는 Number 래퍼 클래스가 있다.
class Stack<E> {
List<E> elements;
public Stack() {
elements = new ArrayList<>();
}
public void push(E e) {
elements.add(e);
}
public E pop() {
E e = elements.get(elements.size()-1);
elements.remove(e);
return e;
}
public boolean isEmpty() {
return elements.size() == 0;
}
public void pushAll(Collection<? extends E> src) {
for(E e : src)
push(e);
}
public void popAll(Collection<? super E> dst) {
while(!isEmpty()) {
dst.add(pop());
}
}
}
이 클래스는 E 타입의 자료형을 저장할 수 있는 스택 자료구조 형태의 클래스이다.
class Test {
public static void main(String[] args) {
Collection<Integer> integers = new ArrayList<>();
integers.add(10);
integers.add(20);
integers.add(30);
Stack<Number> numberStack = new Stack<>();
numberStack.pushAll(integers);
Collection<Object> objects = new ArrayList<>();
numberStack.popAll(objects);
for(Object o : objects) {
System.out.println(o);
}
}
}
스택이 Number 타입의 자료를 받아서 저장하고 꺼낼 수 있게 만들어 놓았다.
만약 pushAll 메서드가 <E> 타입으로 선언되었다면 위의 코드는 에러가 발생한다. Integer가 Number의 하위 자료형이기 때문에 문제가 없을 것 같지만 형인자 자료형인 List는 불변이기 때문에 다른 타입을 저장할 수 없다.
그래서 와일드카드 ? 를 사용하여 위의 코드를 문제없이 동작시킬 수 있는 것이다.
List<ScheduledFuture<?>> scheduledFutures = new ArrayList<>();
Sample.max(scheduledFutures);
Sample.maxEx(scheduledFutures);
class Sample{
public static <T extends Comparable<T>> T max(List<T> list) {
Iterator<T> i = list.iterator();
T result = i.next();
while(i.hasNext()) {
T t = i.next();
if(t.compareTo(result) > 0)
result = t;
}
return result;
}
public static <T extends Comparable<? super T>> T maxEx(List<? extends T> list) {
Iterator<? extends T> i = list.iterator();
T result = i.next();
while(i.hasNext()) {
T t = i.next();
if(t.compareTo(result) > 0)
result = t;
}
return result;
}
}
max는 컴파일 에러가 발생하지만 maxEx는 에러가 발생하지 않는다.
'Java,Android' 카테고리의 다른 글
[Effective Java 규칙30] int 상수 대신 enum을 사용하라 (0) | 2018.10.08 |
---|---|
[Effective Java 규칙29] 형 안전 다형성 컨테이너를 쓰면 어떨지 따져보라 (0) | 2018.10.08 |
[Effective Java 규칙27] 가능하면 제네릭 메서드으로 만들 것 (0) | 2018.10.04 |
[Effective Java 규칙26] 가능하면 제네릭 자료형으로 만들 것 (0) | 2018.10.04 |
[Effective Java 규칙25] 배열대신 리스트를 써라 (0) | 2018.10.04 |