item 29 hyowon - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

[item29] 이왕이면 μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ λ§Œλ“€λΌ

μ•„μ΄ν…œ 7μ—μ„œ 닀룬 μŠ€νƒ μ½”λ“œλ₯Ό μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ λ³€κ²½ν•΄λ³΄μž

λ³€κ²½ μ „

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    
    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);
        }
    }
}

λ³€κ²½ ν›„ - μ»΄νŒŒμΌλ˜μ§€ μ•ŠλŠ”λ‹€.

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

    public Stack() {
        elements = new E[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 static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        for (String arg : args)
            stack.push(arg);
        while (!stack.isEmpty())
            System.out.println(stack.pop().toUpperCase());
    }
}

Objectλ₯Ό E둜 λ°”κΎΈλŠ” λ‹¨κ³„μ—μ„œ 보톡 ν•˜λ‚˜ μ΄μƒμ˜ 였λ₯˜λ‚˜ κ²½κ³ κ°€ λœ¬λ‹€.

μ—¬κΈ°μ„œλŠ” E와 같은 싀체화 λΆˆκ°€ νƒ€μž…μœΌλ‘œ 배열을 λ§Œλ“€ 수 μ—†μ–΄ 였λ₯˜κ°€ λœ¬λ‹€.

ν•΄κ²°μ±…1. μ œλ„€λ¦­ λ°°μ—΄ 생성을 우회

// 였λ₯˜ 제거
public Stack(){
    elements = (E[]) new Object [DEFAULT_INITIAL_CAPACITY]}
}

이제 μ»΄νŒŒμΌλŸ¬λŠ” 였λ₯˜ λŒ€μ‹  κ²½κ³ λ₯Ό 내보낼 것이닀.

λŸ°νƒ€μž„μ— 였λ₯˜κ°€ λ‚  κ°€λŠ₯성이 μžˆλŠ”λ°, μ»΄νŒŒμΌλŸ¬λŠ” κ°€λŠ₯성을 확인할 수 μ—†μ§€λ§Œ μš°λ¦¬λŠ” ν•  수 μžˆλ‹€.

μ•„λž˜ λ°°μ—΄ elementsλŠ” private ν•„λ“œμ— μ €μž₯되고, ν΄λΌμ΄μ–ΈνŠΈλ‘œ λ°˜ν™˜λ˜κ±°λ‚˜ λ‹€λ₯Έ λ©”μ„œλ“œμ— μ „λ‹¬λ˜λŠ” 일이 μ—†λ‹€.

λ˜ν•œ push λ©”μ„œλ“œλ‘œ μ €μž₯λ˜λŠ” μ›μ†Œμ˜ νƒ€μž…μ€ 항상 E이닀. λ”°λΌμ„œ 이 비검사 ν˜•λ³€ν™˜μ€ μ•ˆμ „ν•˜λ‹€.

// 경고 제거
@SuppressWarnings("unchecked")
public Stack(){
    elements = (E[]) new Object [DEFAULT_INITIAL_CAPACITY]}
}

μ•ˆμ „ν•¨μ„ μ½”λ“œμƒμœΌλ‘œ ν™•μΈν–ˆμœΌλ‹ˆ @SuppressWarnings 을 μ΅œμ†Œ λ²”μœ„λ‘œ λΆ™μ—¬ κ²½κ³ λ₯Ό μˆ¨κΈ΄λ‹€.(item27)

μ–΄λ…Έν…Œμ΄μ…˜μ„ 달면 Stack이 κΉ”λ”ν•˜κ²Œ 컴파일되고, λͺ…μ‹œμ μœΌλ‘œ ν˜•λ³€ν™˜ν•˜μ§€ μ•Šμ•„λ„ ClassCastException κ±±μ • 없이 μ‚¬μš©ν•  수 있게 λœλ‹€.

ν•΄κ²°μ±…2. elementsν•„λ“œμ˜ νƒ€μž…μ„ E[] β†’ Object[]둜 λ³€κ²½ν•œλ‹€.

public class Stack<E> {
        private Object[] elements; // <---------
        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();
            }
 
            E result = (E) elements[--size]; // <------------ <1>
            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);
            }
        }
    }

<1> : Object 배열을 E νƒ€μž… result에 λŒ€μž…ν•˜λ € ν•΄μ„œ 였λ₯˜κ°€ λœ¨λ‹ˆ, ν˜•λ³€ν™˜ν•΄ λŒ€μž…ν•œλ‹€.

그럼 κ²½κ³ κ°€ λœ¨λŠ”λ° λ§ˆμ°¬κ°€μ§€λ‘œ κ°œλ°œμžκ°€ 직접 λŸ°νƒ€μž„ 였λ₯˜κ°€ λ‚  ꡬ석이 μ—†λŠ”μ§€ 확인 ν›„, μ–΄λ…Έν…Œμ΄μ…˜μ„ 뢙인닀.

public E pop(){
    // 비검사 κ²½κ³ λ₯Ό 적절히 μˆ¨κΈ΄λ‹€.
    if(size == 0){
         throw new EmptyStackException();
    }

    @SuppressWarnings("unchecked")
    E result = (E) elements[--size];

    elements[size] = null; // λ‹€ μ“΄ μ°Έμ‘° ν•΄μ œ
    return result;
}

두 λ°©λ²•μ˜ μž₯단점

ν•΄κ²°μ±…1. μ œλ„€λ¦­ λ°°μ—΄ 생성을 우회

  • 가독성이 μ’‹λ‹€
  • (ν˜•λ³€ν™˜μ„ λ°°μ—΄ 생성 μ‹œ ν•œ 번만 ν•΄μ£Όλ©΄ λ˜λ‹ˆ)μ½”λ“œκ°€ 더 짧아진닀.
  • λ°°μ—΄μ˜ λŸ°νƒ€μž„νƒ€μž…μ΄ μ»¨νƒ€μΌνƒ€μž„νƒ€μž…κ³Ό 달라 νž™ μ˜€μ—Ό(item 32)을 μΌμœΌν‚¨λ‹€.
  • νž™ μ˜€μ—Ό(heap pollution) : νŒŒλΌλ―Έν„° ν™” 된 ν˜•νƒœμ˜ λ³€μˆ˜κ°€ 맀개 λ³€μˆ˜ μœ ν˜•μ΄ μ•„λ‹Œ 객체λ₯Ό μ°Έμ‘° ν•  λ•Œ λ°œμƒν•˜λŠ” 상황
public class HeapPollutionDemo {
   public static void main(String[] args) {
      Set s = new TreeSet<Integer>();
      Set<String> ss = s;            // unchecked warning
      s.add(new Integer(42));        // another unchecked warning
      Iterator<String> iter = ss.iterator();
      while (iter.hasNext()) {
         String str = iter.next();   // ClassCastException thrown
         System.out.println(str);
      }
   }
}

ν•΄κ²°μ±…2. elementsν•„λ“œμ˜ νƒ€μž…μ„ E[] β†’ Object[]둜 λ³€κ²½

  • 1보닀 μ½”λ“œκ°€ 더 길어진닀.
  • νž™ μ˜€μ—Όμ΄ μ—†λ‹€.

기타

μ•„μ΄ν…œ 28의 "λ°°μ—΄λ³΄λ‹€λŠ” 리슀트λ₯Ό μš°μ„ ν•˜λΌ" λŠ” 말과 λͺ¨μˆœλ˜λŠ” μ˜ˆμ œμ΄μ§€λ§Œ

μžλ°”μ˜ κΈ°λ³Έ νƒ€μž…μ— λ¦¬μŠ€νŠΈκ°€ μ œκ³΅λ˜μ§€ μ•Šμ•„ κ²°κ΅­μ—” 리슀트λ₯Ό λ°°μ—΄λ‘œ κ΅¬ν˜„ν•΄μ•Ό ν•˜λ©°,

μ„±λŠ₯상 이점을 μœ„ν•΄ 배열을 μΌλΆ€λŸ¬ μ‚¬μš©ν•˜κΈ°λ„ ν•œλ‹€.

μ œλ„€λ¦­ νƒ€μž…μ— μ œμ•½μ„ λ‘˜ μˆ˜λ„ μžˆλ‹€.

DelayQueue의 μ›μ†Œμ—μ„œ ν˜•λ³€ν™˜ 없이 λ°”λ‘œ Delayed 클래슀의 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 있고, ClassCastException 걱정을 ν•  ν•„μš”λ„ μ—†λ‹€.

class DelayQueue<E extends Delayed> implements BlockingQueue<E>

λͺ¨λ“  νƒ€μž…μ€ 자기 μžμ‹ μ˜ ν•˜μœ„ νƒ€μž…μ΄λ―€λ‘œ DelayQueueλ‘œλ„ μ‚¬μš©ν•  수 μžˆλ‹€.

κ²°λ‘ 

μƒˆλ‘œμš΄ νƒ€μž…μ„ 섀계할 λ•ŒλŠ” ν˜•λ³€ν™˜ 없이도 μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•˜λΌ.

κ·Έλ ‡κ²Œ ν•˜λ €λ©΄ μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ λ§Œλ“€μ–΄μ•Ό ν•  κ²½μš°κ°€ λ§Žλ‹€.

⚠️ **GitHub.com Fallback** ⚠️