// Generic stack with bulk methods using wildcard types - package org.effectivejava.examples.chapter05.item28; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; public class Stack<E> { private E[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; // The elements array will contain only E instances from push(E). // This is sufficient to ensure type safety, but the runtime // type of the array won't be E[]; it will always be 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; // Eliminate obsolete reference return result; } public boolean isEmpty() { return size == 0; } private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } // pushAll method without wildcard type - deficient! // public void pushAll(Iterable<E> src) { // for (E e : src) // push(e); // } // Wildcard type for parameter that serves as an E producer public void pushAll(Iterable<? extends E> src) { for (E e : src) push(e); } // popAll method without wildcard type - deficient! // public void popAll(Collection<E> dst) { // while (!isEmpty()) // dst.add(pop()); // } // Wildcard type for parameter that serves as an E consumer public void popAll(Collection<? super E> dst) { while (!isEmpty()) dst.add(pop()); } // Little program to exercise our generic Stack public static void main(String[] args) { Stack<Number> numberStack = new Stack<Number>(); Iterable<Integer> integers = Arrays.asList(3, 1, 4, 1, 5, 9); numberStack.pushAll(integers); Collection<Object> objects = new ArrayList<Object>(); numberStack.popAll(objects); System.out.println(objects); } }