1. PECS ๐
PECS(Producer-Extends, Consumer-Super)๋ ๋งค๊ฐ๋ณ์ํ ํ์ T๊ฐ ์์ฐ์๋ผ๋ฉด <? extends T>๋ฅผ ์ฌ์ฉํ๊ณ , ์๋น์๋ผ๋ฉด <? super T>๋ฅผ ์ฌ์ฉํ๋ผ๋ ๊ฒ์ด๋ค.
์์์ ํจ๊ป PECS๋ฅผ ์ดํดํด ๋ณด๋๋ก ํ์.
public class Stack<E> {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
// ๋ฐฐ์ด elements๋ push(E)๋ก ๋์ด์จ E ์ธ์คํด์ค๋ง ๋ด๋๋ค.
// ๋ฐ๋ผ์ ํ์
์์ ์ฑ์ ๋ณด์ฅํ์ง๋ง,
// ์ด ๋ฐฐ์ด์ ๋ฐํ์ ํ์
์ E[]๊ฐ ์๋ Object[]๋ค!
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(E e) {
ensureCapacity();
elements[size++] = e;
}
public E pop() {
if(size == 0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null; // ๋ค ์ด ์ฐธ์กฐ ๊ฐ์ฒด ํด์
return result;
}
public boolean isEmpty() {
return size == 0;
}
private void ensureCapacity() {
if(elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
public void pushAll(Iterable<E> src) {
for(E e : src)
push(e);
}
public void popAll(Collection<E> dst) {
while(!isEmpty())
dst.add(pop());
}
}
์ฝ๋์์ ํ์ธํ ์ ์๋ ๊ฒ์ฒ๋ผ ์ง๊ธ๊น์ง๋ ํ์ ๋งค๊ฐ๋ณ์ E๋ง์ ์ฌ์ฉํ์๋ค. ์ฆ, ํ๋์ ํ์ ๋ง ์ง์ ํด์ ์ฌ์ฉํ ๊ฒ์ด๋ค.
์ ๋ค๋ฆญ์ ๋ถ๊ณต๋ณ์ด๊ธฐ ๋๋ฌธ์ ์๋ ์ฝ๋์์ ํ์ธํ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ค๋ฅธ ํ์ ์ ๋ฃ์ง ๋ชปํ๊ฒ ๋๋ค.
public static void main(String[] args) {
Stack<Number> numberStack = new Stack<>();
Iterable<Number> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numberStack.pushAll(numbers); // ๊ฐ๋ฅ
Iterable<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6);
numberStack.pushAll(integers); // ๋ถ๊ฐ๋ฅ // ์ปดํ์ผ ์๋ฌ
}
ํ์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก Stack<Number>์ Integer๋ฅผ ๋ฃ๋ ๊ฒ์ด ๋ฌธ์ ๊ฐ ๋์ง๋ ์๋๋ค ํด๋นํ๋ ๊ฐ์ฒด์ ์์ ํ์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ๋์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋์ ์๋์ ๊ฐ์ด ํ์ ์ ์์ผ๋์นด๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
// ๊ธฐ์กด
public void pushAll(Iterable<E> src) {
for(E e : src)
push(e);
}
// ๋ณ๊ฒฝ - ํ์ ์ ์์ผ๋์นด๋ ์ฌ์ฉ
public void pushAll(Iterable<? extends E> src) {
for(E e : src)
push(e);
}
public static void main(String[] args) {
Stack<Number> numberStack = new Stack<>();
Iterable<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6);
numberStack.pushAll(integers);
Iterable<Double> doubles = Arrays.asList(1.0, 2.1, 3.2, 4.3, 5.4, 6.5);
numberStack.pushAll(doubles);
}
์ด๋ ๊ฒ ํ๋ฉด Number์ ํ์ ํ์ ๋ค์ ๋ฃ์ ์ ์๋ค.
์ด๋ฌํ ์ญํ ์ ํ๋ ๊ฒ์ ์์ฐ์(Producer)๋ผ๊ณ ํ๋๋ฐ ์์ฐ์์์๋ extends๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ์ฌ์ฉํ๊ณ ์๋ E์ ํ์ ํ์ ์ ๋ฐ์์ ๋ฃ์ด๋ ๋ฌธ์ ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค
pushAll๋ก ๋ฃ๋ ๊ฒ์ ์ดํด๋ณด์์ผ๋ฏ๋ก ๊บผ๋ด๋ ๊ฒ์ธ popAll๋ ์ดํด๋ณด๋๋ก ํ์
๊บผ๋ผ ๋์๋ ํด๋น ํ์ E๋ณด๋ค ๋ ์์ ํ์ ์ผ๋ก ๊บผ๋ผ ์ ์๋ค. ์๋ฅผ ๋ค์ด E๊ฐ Number์ธ ๊ฒฝ์ฐ Object๋ก ๊บผ๋ผ ์ ์๋ค๋ ๊ฒ์ด๋ค.
ํ์ง๋ง ์๋์ ๊ฐ์ด ํ์ฌ๋ ํ์ ํ๋๋ก ์ ์ธ์ด ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ์ ์๋๋๋ก ์ฌ์ฉํ์ง ๋ชปํ๋ค.
// ๊ธฐ์กด
public void pushAll(Iterable<E> src) {
for(E e : src)
push(e);
}
๊ทธ๋์ ์ด๋ฐ ๊ฒฝ์ฐ์๋ ํ์ ์ ์์ผ๋์นด๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
// ๋ณ๊ฒฝ - ํ์ ์ ์์ผ๋์นด๋ ์ฌ์ฉ
public void pushAll(Iterable<? extends E> src) {
for(E e : src)
push(e);
}
public static void main(String[] args) {
Stack<Number> numberStack = new Stack<>();
Collection<Object> objects = new ArrayList<>();
numberStack.popAll(objects);
}
์ฆ, ์ด๋ ๊ฒ pushAll๊ณผ ๊ฐ์ด ์์ฐ์(Provider) ์ญํ ์ ํ ๋์๋ extends๋ฅผ ์ฌ์ฉํ๊ณ popAll๊ณผ ๊ฐ์ด ์๋น์(Consumer) ์ญํ ์ ํ ๋์๋ super๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
์ด๊ฒ์ด PECS(Producer-Extends, Consumer-Super) ๊ท์น์ด๋ค.
2. ํ์ ๋งค๊ฐ๋ณ์ VS ์์ผ๋์นด๋ ๐
ํ์ ๋งค๊ฐ๋ณ์์ ์์ผ๋์นด๋์๋ ๊ณตํต๋๋ ๋ถ๋ถ์ด ์์ด์, ๋ฉ์๋๋ฅผ ์ ์ํ ๋ ๋ ์ค ์ด๋ ๊ฒ์ ์ฌ์ฉํด๋ ๊ด์ฐฎ์ ๋๊ฐ ๋ง๋ค.
swap์ด๋ผ๋ ๋ฉ์๋๋ฅผ ์ ์ํ๋ค๊ณ ํ ๋ ์๋์ ๊ฐ์ด ๋ ๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ ์ธํ ์ ์๋ค.
// ํ์
๋งค๊ฐ๋ณ์ ์ฌ์ฉ
public static <E> void swap(List<E> list, int i, int j);
// ์์ผ๋์นด๋ ์ฌ์ฉ
public static void swap(List<?> list, int i, int j);
๋ง์ฝ public API๋ผ๊ณ ํ๋ค๋ฉด ๋ ๋ฒ์งธ๊ฐ ๋ซ๋ค. ์ด๋ค ๋ฆฌ์คํธ๋ ์ด ๋ฉ์๋์ ๋๊ธฐ๋ฉด ๋ช ์ํ ์ธ๋ฑ์ค์ ์์๋ค์ ๊ตํํด ์ค ๊ฒ์ด๊ณ , ์ ๊ฒฝ ์จ์ผ ํ ํ์ ๋งค๊ฐ๋ณ์๋ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ธฐ๋ณธ ๊ท์น์ ๋ค์๊ณผ ๊ฐ๋ค. ๋ฉ์๋ ์ ์ธ์ ํ์ ๋งค๊ฐ๋ณ์๊ฐ ํ ๋ฒ๋ง ๋์ค๋ฉด ์์ผ๋์นด๋๋ก ๋์ฒดํ๋ผ๋ ๊ฒ์ด๋ค.
์ด๋ ๋นํ์ ์ ํ์ ๋งค๊ฐ๋ณ์๋ผ๋ฉด ๋นํ์ ์ ์์ผ๋์นด๋๋ก ๋ฐ๊พธ๊ณ , ํ์ ์ ํ์ ๋งค๊ฐ๋ณ์๋ผ๋ฉด ํ์ ์ ์์ผ๋์นด๋๋ก ๋ฐ๊พธ๋ฉด ๋๋ค.
ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ๋ฉด ์ปดํ์ผ๋์ง ์๋๋ค.
public class Swap {
public static void swap(List<?> list, int i, int j) {
list.set(i, list.set(j, list.get(i)));
}
}
List<?>์๋ null ์ธ์๋ ์ด๋ค ๊ฐ๋ ๋ฃ์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ์๋์ ๊ฐ์ด ๋์ฐ๋ฏธ ๋ฉ์๋๋ฅผ ๋ฐ๋ก ์์ฑํด์ ์ฌ์ฉํด์ผ ํ๋ค.
public class Swap {
public static void swap(List<?> list, int i, int j) {
swapHelper(list, i, j);
}
private static <E> void swapHelper(List<E> list, int i, int j){
list.set(i, list.set(j, list.get(i)));
}
}
ํด๋น ๊ธ์ ๋ฐฑ๊ธฐ์ ๋์ '์ดํํฐ๋ธ ์๋ฐ ์๋ฒฝ ๊ณต๋ต'์ ์ฐธ๊ณ ํ์์ต๋๋ค.