Nested Classes
An Introduction with Examples in Java |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
Course
class
that has associated Comparator
classes; a ClosedInterval
class that
has associated Iterator
classes)Containment
Course
class with "top-level"
CreditComparator
and IDComparator
classesComparator
classes
will only ever be used with the Course
class
(i.e., they can't stand alone), it makes sense
to make them static nested classes
import java.util.*; /** * A simple encapsulation of a course. * * @author Prof. David Bernstein, James Madison University * @version 2.0 (Static Nested Classes) */ public class Course { private int credits; private String department, number; /** * Explicit Value Constructor. * * @param depatment The department identifier (e.g., "CS") * @param number The course nbumber (e.g., "159") * @param credits The number of credits */ public Course(String department, String number, int credits) { this.department = department; this.number = number; this.credits = credits; } /** * Returns the number of credits asscoiated with this Course. * * @return The number of credits */ public int getCredits() { return credits; } /** * Returns the ID of this Course. * * @return The ID */ public String getID() { return department + number; } /** * Return a String representation of this Course. * * @return The String representation */ public String toString() { return getID() + " (" + getCredits() + "cr)"; } /** * A Comparator for Course objects that uses the number of credits. */ public static class CreditComparator implements Comparator<Course> { /** * Compares two Course objects (using their credit hours) * (required by Comparator). * * @param a Object a * @param b Object b * @return -1, 0, 1 (as per Comparator) */ public int compare(Course a, Course b) { int an, bn; an = a.getCredits(); bn = b.getCredits(); if (an < bn) return -1; else if (an > bn) return 1; else return 0; } } /** * A Comparator for Course objects that uses the ID. */ public static class IDComparator implements Comparator<Course> { /** * Compares two Course objects (using their IDs) * (required by Comparator). * * @param a Object a * @param b Object b * @return -1, 0, 1 (as per Comparator) */ public int compare(Course a, Course b) { return a.getID().compareTo(b.getID()); } } }
import java.util.*; /** * An application that can be used to demonstrate the power * of the Comparator interface. * * @author Prof. David Bernstein, James Madison University * @version 2.0 (Static Nested Classes) */ public class CourseDriver { /** * The entry point of the application. * * @param args The command-line arguments */ public static void main(String[] args) { Comparator<Course> comparator; Course[] prog; prog = new Course[3]; prog[0] = new Course("CS", "240", 3); prog[1] = new Course("CS", "159", 3); prog[2] = new Course("CS", "139", 4); // Note that because IDComparator is a static nested class, // its constructor must be referred to using the name of the // outer class. comparator = new Course.IDComparator(); Arrays.sort(prog, comparator); System.out.println("\nSorted by ID:"); print(prog); comparator = new Course.CreditComparator(); Arrays.sort(prog, comparator); System.out.println("\nSorted by Credits:"); print(prog); } /** * Print an array of Course objects. * * @param courses The array. */ private static void print(Course[] courses) { for (int i=0; i<courses.length; i++) { System.out.println(courses[i]); } } }
ClosedInterval
class and associated
IncreasingIterator
classIncreasingIterator
object is associated with
a particular ClosedInterval
object
import java.util.*; /** * An encapsulation of a closed interval on the real line. * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public class ClosedInterval { private double left, right; /** * Explicit value constructor. * * @param left The lower bound of the interval * @param right The upper bound of the interval */ public ClosedInterval(double left, double right) { this.left = left; this.right = right; } /** * Get an increasing integer Iterator (i.e., from left to right) * for this interval. * * @return The Iterator */ public Iterator<Integer> getIncreasingIterator() { return new IncreasingIterator(this); } /** * Get the lower bound for this interval. * * @return The lower bound */ public double getLeft() { return left; } /** * Get the upper bound for this interval. * * @return The upper bound */ public double getRight() { return right; } }
import java.util.*; /** * An Iterator that returns the Integer objects in a ClosedInterval * from left to right. * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public class IncreasingIterator implements Iterator<Integer> { private ClosedInterval interval; private int next; /** * Constructor. * * @param interval The ClosedInterval to iterate over */ public IncreasingIterator(ClosedInterval interval) { this.interval = interval; next = (int)Math.ceil(interval.getLeft()); } /** * Returns true if this Iterator has a next element, * and false otherwise. * * @return true or false as appropriate */ public boolean hasNext() { return next <= interval.getRight(); } /** * Return the next Integer in the interval. * * @return The next Integer. * @throws NoSuchElementException if there is no next Integer */ public Integer next() throws NoSuchElementException { if (!hasNext()) throw new NoSuchElementException(); int result; result = next; ++next; return Integer.valueOf(result); } }
import java.util.*; /** * An encapsulation of a closed interval on the real line. * * @author Prof. David Bernstein, James Madison University * @version 2.0 (Inner Class) */ public class ClosedInterval { private double left, right; /** * Explicit value constructor. * * @param left The lower bound of the interval * @param right The upper bound of the interval */ public ClosedInterval(double left, double right) { this.left = left; this.right = right; } /** * Get an increasing integer Iterator (i.e., from left to right) * for this interval. * * @return The Iterator */ public Iterator<Integer> getIncreasingIterator() { return new IncreasingIterator(); } /** * Get the lower bound for this interval. * * @return The lower bound */ public double getLeft() { return left; } /** * Get the upper bound for this interval. * * @return The upper bound */ public double getRight() { return right; } /** * An Iterator that returns the Integer objects in this * interval from left to right. */ private class IncreasingIterator implements Iterator<Integer> { private int next; /** * Constructor. */ private IncreasingIterator() { next = (int)Math.ceil(left); } /** * Returns true if this Iterator has a next element, * and false otherwise. * * @return true or false as appropriate */ public boolean hasNext() { return next <= right; } /** * Return the next Integer in the interval. * * @return The next Integer. * @throws NoSuchElementException if there is no next Integer */ public Integer next() throws NoSuchElementException { if (!hasNext()) throw new NoSuchElementException(); int result; result = next; ++next; return Integer.valueOf(result); } } }
import java.util.*; /** * An application that can be used to demonstrate the use of * an inner class (i.e., a non-static nested class). * * @author Prof. David Bernstein, James Madison University * @version 2.0 (Inner Classes) */ public class IntervalDriver { /** * The entry point of the application. * * @param args The command-line arguments */ public static void main(String[] args) { ClosedInterval interval; Iterator<Integer> iterator; interval = new ClosedInterval(3.7, 10.2); // Note because the IncreasingIterator class is an inner class // (i.e., non-static nested class), an instance of the // ClosedInterval class is needed to construct an instance of // the IncreasingIterator class. iterator = interval.getIncreasingIterator(); while (iterator.hasNext()) { System.out.printf("%d\n", iterator.next()); } } }