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