Item 29. Generic Type

์ด์™•์ด๋ฉด ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ๋งŒ๋“ค๋ผ

ํด๋ผ์ด์–ธํŠธ์—์„œ ์ง์ ‘ ํ˜•๋ณ€ํ™˜ํ•ด์•ผํ•˜๋Š” ๊ฒƒ๋ณด๋‹จ ํ˜•๋ณ€ํ•œ ์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„  ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ์„ค๊ณ„ํ•  ๋• ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ๊ณ ๋ คํ•ด๋ณด๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ

์ œ๋„ค๋ฆญ ํƒ€์ž… ์ ์šฉ ์ „ ์ฝ”๋“œ

class Stack {
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    private Object[] elements;
    private int size = 0;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        Object 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);
        }
    }
}

class Main {

    public static void main(String[] args) {
        Stack stack = new Stack();

        stack.push("Hello");
        stack.push("Ogu");

        while (!stack.isEmpty()) {
            System.out.println(stack.pop());
        }
    }
}

์œ„์™€ ๊ฐ™์€ Stack ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ œ๋„ค๋ฆญ์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์œ„์ฒ˜๋Ÿผ ์ œ๋„ค๋ฆญ ์ฝ”๋“œ๋ฅผ ์ ์šฉํ•˜๋”๋ผ๋„ ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋„ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.(๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€๋งŒ Raw Type์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์žˆ์–ด ์—๋Ÿฌ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ)

์ œ๋„ค๋ฆญ ํƒ€์ž… ์ ์šฉ ์ฝ”๋“œ

class Stack<E> {
    private E[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY]; // ๊ฒฝ๊ณ  ๋ฐœ์ƒ, Unchecked cast: 'java.lang.Object[]' to 'E[]'
    }

    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);
        }
    }
}


class Main {

    public static void main(String[] args) {
        // ๊ฒฝ๊ณ  ๋ฐœ์ƒ, Raw use of parameterized class 'Stack'
        Stack stack = new Stack();

        stack.push("Hello");
        stack.push("Ogu");

        while (!stack.isEmpty()) {
            System.out.println(stack.pop());
        }
    }
}

ํด๋ผ์ด์–ธํŠธ(Main) ์ฝ”๋“œ์˜ ๊ฒฝ๊ณ ๋„ ๋ฐœ์ƒํ•˜์ง€๋งŒ, ์ƒ์„ฑ์ž์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด @SuppressWarnings("unchecked") ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

@SuppressWarnings("unchecked") ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

์ƒ์„ฑ์ž์— @SuppressWarnings("unchecked") ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ํ•„๋“œ์˜ elements๋ฅผ Object ๋ฐฐ์—ด๋กœ ์„ ์–ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ๋‘ ๋ฐฉ๋ฒ•์— ์ •๋‹ต์ด ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ ์žฅ/๋‹จ์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒํ™ฉ์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  • ์ƒ์„ฑ์ž์— @SuppressWarnings("unchecked") ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

class Stack<E> {

    // ...

    // ๋ฉ”์„œ๋“œ์— ์ ์šฉ
    @SuppressWarnings("unchecked")
    public Stack() {
        elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
    }

    // ...
}

์ปดํŒŒ์ผ๋Ÿฌ์—์„  ํƒ€์ž… ์•ˆ์ „ํ•œ์ง€ ์ฆ๋ช…ํ•  ์ˆ˜ ์—†์ง€๋งŒ, ๊ฐœ๋ฐœ์ž๋Š” ํƒ€์ž… ์•ˆ์ „ํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์œ„ ์ฝ”๋“œ์—์„œ๋Š” ์•„๋ž˜์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ž… ์•ˆ์ „ํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. elements๊ฐ€ private ํ•„๋“œ์— ์ €์žฅ๋จ: ํด๋ผ์ด์–ธํŠธ์—์„œ ์ง์ ‘ ์ ‘๊ทผ ๋ถˆ๊ฐ€

  2. ํด๋ผ์ด์–ธํŠธ๋‚˜ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌ๋˜๋Š” ์ผ์ด ์—†์Œ: elements ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์•„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Œ

  3. push ๋ฉ”์„œ๋“œ์—์„œ elements ๋ฐฐ์—ด์— ์ €์žฅ๋˜๋Š” ํƒ€์ž…์„ E๋กœ ์ง€์ •: elements ๋ฐฐ์—ด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์œ ์ผํ•œ ๋ฉ”์„œ๋“œ์ด๋ฉฐ, elements ๋ฐฐ์—ด์— ์ €์žฅ๋˜๋Š” ์›์†Œ์˜ ํƒ€์ž…์ด E๋กœ ํ•œ์ •๋˜์–ด ์žˆ์Œ

์ด ๋ฐฉ๋ฒ•์€ ๊ฐ€๋…์„ฑ์ด ๋” ์ข‹์œผ๋ฉฐ, elements ๋ฐฐ์—ด ์ƒ์„ฑ ์‹œ ํ•œ ๋ฒˆ๋งŒ ํ˜•๋ณ€ํ™˜์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ„ํŽธํ•˜๋‹ค. ํ•˜์ง€๋งŒ ๋ฐฐ์—ด์˜ ๋Ÿฐํƒ€์ž„ ํƒ€์ž…์ด ์ปดํŒŒ์ผํƒ€์ž„ ํƒ€์ž…๊ณผ ๋‹ฌ๋ผ์ง€๊ธฐ ๋•Œ๋ฌธ์—(Generic Type Erasure) ํž™ ์˜ค์—ผ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.(์œ„ ์ฝ”๋“œ์—์„  ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ)

** ํž™ ์˜ค์—ผ(Heap Pollution): JVM ํž™ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ์˜ค์—ผ์ด ๋œ ์ƒํƒœ, ์ œ๋„ค๋ฆญ์—์„œ์˜ ํž™ ์˜ค์—ผ์€ ์ ์šฉ๋œ ์ œ๋„ค๋ฆญ ํƒ€์ž…๊ณผ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธ

  • ํ•„๋“œ์˜ elements๋ฅผ Object ๋ฐฐ์—ด๋กœ ์„ ์–ธ

class Stack<E> {
    private Object[] elements; // E -> Object ๋ณ€๊ฒฝ
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(E e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public E pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        @SuppressWarnings("unchecked")      // ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๋ณด์žฅ๋˜์ง€ ์•Š์Œ์„ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€
        E result = (E) elements[--size];    // Object ๋ฐฐ์—ด์ด๊ธฐ ๋•Œ๋ฌธ์— ํ˜•๋ณ€ํ™˜ ์ถ”๊ฐ€
        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);
        }
    }
}

Object ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— pop()์—์„œ ํ˜• ๋ณ€ํ™˜์ด ํ•„์š”ํ•œ๋ฐ, ์ด๋•Œ๋„ @SuppressWarnings("unchecked") ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ฒฝ๊ณ ๋ฅผ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ์—๋„ ์•ˆ์ „ํ•œ ์ด์œ ๋Š” ์œ„์™€ ๋™์ผํ•˜๋‹ค.

์ด ๋ฐฉ๋ฒ•์€ ํ˜•๋ณ€ํ™˜์„ ํ•˜๋Š” ๋ถ€๋ถ„์ด ๋งŽ์•„ ์งˆ ์ˆ˜ ์žˆ์–ด ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๊ณ , elements ๋ฐฐ์—ด ์ƒ์„ฑ ์‹œ ๋งค๋ฒˆ ํ˜•๋ณ€ํ™˜์„ ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋งŒํผ ํ˜• ๋ณ€ํ™˜์˜ ๋ฒ”์œ„๊ฐ€ ์ตœ์†Œํ™”๋˜๊ณ  ํž™ ์˜ค์—ผ์˜ ์œ„์น˜๋„ ์ตœ์†Œํ™”๋˜๊ธฐ ๋•Œ๋ฌธ์— ํž™ ์˜ค์—ผ์— ๋Œ€ํ•ด ๋” ์•ˆ์ „ํ•˜๋‹ค.

์ œํ•œ์ด ํ•„์š”ํ•œ ์ œ๋„ค๋ฆญ

์ œ๋„ค๋ฆญํƒ€์ž…์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์— ์•„๋ฌด๋Ÿฐ ์ œ์•ฝ์„ ๋‘์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ํƒ€์ž…์„ ์ˆ˜์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ํ•„์š”์— ๋”ฐ๋ผ ํŠน์ • ํƒ€์ž…๋งŒ ์ˆ˜์šฉํ•˜๋„๋ก ์ƒํ™ฉ์—๋Š” ์ œํ•œ์„ ๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

// Delayed ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋งŒ ์ˆ˜์šฉํ•˜๋„๋ก ์ œํ•œ์„ ๋‘์–ด ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋ณด์žฅ
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
        implements BlockingQueue<E> {
    // ...
}

Last updated

Was this helpful?