Section 4.3. Nested Classes


4.3. Nested Classes

Java permits nesting one class inside another. If the outer class has type parameters and the inner class is not static, then type parameters of the outer class are visible within the inner class.

Example 4.1 shows a class implementing collections as a singly-linked list. The class extends java.util.AbstractCollection, so it only needs to define the methods size, add, and iterator. The class contains an inner class, Node, for the list nodes, and an anonymous inner class implementing Iterator<E>. The type parameter E is in scope within both of these classes.

Example 4-1. Type parameters are in scope for nested, nonstatic classes

 public class LinkedCollection<E> extends AbstractCollection<E> {   private class Node {     private E element;     private Node next = null;     private Node(E elt) { element = elt; }   }   private Node first = new Node(null);   private Node last = first;   private int size = 0;   public LinkedCollection() {}   public LinkedCollection(Collection<? extends E> c) { addAll(c); }   public int size() { return size; }   public boolean add(E elt) {     last.next = new Node(elt); last = last.next; size++;     return true;   }   public Iterator<E> iterator() {     return new Iterator<E>() {       private Node current = first;       public boolean hasNext() {         return current.next != null;       }       public E next() {         if (current.next != null) {           current = current.next;           return current.element;         } else throw new NoSuchElementException();       }       public void remove() {         throw new UnsupportedOperationException();       }     };   } } 

For contrast, Example 4.2 shows a similar implementation, but this time the nested Node class is static, and so the type parameter E is not in scope for this class. Instead, the nested class is declared with its own type parameter, T. Where the previous version referred to Node, the new version refers to Node<E>. The anonymous iterator class in the preceding example has also been replaced by a nested static class, again with its own type parameter.

Example 4-2. Type parameters are not in scope for nested, static classes

 class LinkedCollection<E> extends AbstractCollection<E> {   private static class Node<T> {     private T element;     private Node<T> next = null;     private Node(T elt) { element = elt; }   }   private Node<E> first = new Node<E>(null);   private Node<E> last = first;   private int size = 0;   public LinkedCollection() {}   public LinkedCollection(Collection<? extends E> c) { addAll(c); }   public int size() { return size; }   public boolean add(E elt) {     last.next = new Node<E>(elt); last = last.next; size++;     return true;   }   private static class LinkedIterator<T> implements Iterator<T> {     private Node<T> current;     public LinkedIterator(Node<T> first) { current = first; }     public boolean hasNext() {       return current.next != null;     }     public T next() {       if (current.next != null) {         current = current.next;         return current.element;       } else throw new NoSuchElementException();     }     public void remove() {       throw new UnsupportedOperationException();     }   }   public Iterator<E> iterator() {     return new LinkedIterator<E>(first);   } } 

If the node classes had been made public rather than private, you would refer to the node class in the first example as LinkedCollection<E>.Node, whereas you would refer to the node class in the second example as LinkedCollection.Node<E>.

Of the two alternatives described here, the second is preferable. Nested classes that are not static are implemented by including a reference to the enclosing instance, since they may, in general, access components of that instance. Static nested classes are usually both simpler and more efficient.




Java Generics and Collections
Java Generics and Collections
ISBN: 0596527756
EAN: 2147483647
Year: 2006
Pages: 136

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net