In this homework, you will complete the implementation of a simple GUI application to gravitational simulations. You will also use a collection class with an interface based on Java's library collection system.
In this week, you will work with several concepts that don't have their own chapter in the textbook.
A Java ``interface'' is a special kind of ``abstract class.''
A Java interface specifies a set of (public) operations that an ADT
might be expected to implement. An ADT implementation signals its
adherence to the interface by adding ``implements
''
to the class header, where
is the name of the interface.
A Java variable (field, parameter or local) may have an interface as a type. Of course the variable is not an instance of this type, since interfaces are abstract--they don't provide any implementation. Instead they are instances of some class that implements the interface. In Java, it is considered better to use interfaces for the type of variables or method returns instead of concrete classes since it makes the program more general.
In this assignment, you will need to use
an interface called ActionListener and
one ``generic'' interface both described later.
A generic class has type parameters enclosed in angle brackets,
for example class ArrayList<T>; here
is the only generic
type parameter. Inside the body of the class
can be used as a
regular type. When the class is used, you need to instantiate it with
an actual type parameter, for instance String or
Particle. Writing generic classes is somewhat involved,
and so we delay such an assignment
until week 6 or 7.
Soon after Java was released, the need for a standardized collections framework became apparent. Accordingly, Java 1.2 introduced a standard collections framework. Each of the collection classes implements a standard set of operations including the following (among others):
edu.uwm.cs351.util.Collection<E>. We give an implementation of this
interface in class edu.uwm.cs351.util.ArrayList<E>.
This class is a stripped down version of the Java library class
java.util.ArrayList. For this Homework, don't use the standard
Java library Collection or ArrayList.
Java's external iterators have the following methods:
hasNext() should have returned
false), then throw an instance of NoSuchElementException.
next() from
the collection. Throws an instance of class IllegalStateException if
next() has not yet been called or if the element has already
been removed.
Iterator interface is generic with the type of the elements
in the collection.
To access all the elements of a collection, and decide whether to
delete them, one can write:
Java has a special syntax of ``for'' loops to make it easy to use iterators. The shortcut:
When using standard Java collections,
(external) iterators become ``stale'' if the collection changes, except by using
the iterator's own remove method. It is not legal to
use a stale iterator for anything, even calling hasNext.
In other words, if you request an iterator and later add an element to
the collection, then you are not allowed to use the iterator again.
If you want an iterator, you must request a new one.
Implementors of Java's standard collections are encouraged to provide fail fast implementations of iterators which ``usually'' throw an exception (an instance of ConcurrentModificationException) when a stale iterator is used. A ``fail fast'' implementation is not an absolute requirement.
The stripped-down ArrayList CS 351 library class
has this ``feature.''
This week, we will work with the ``action listener'' interface:
public interface ActionListener {
public void actionPerformed(ActionEvent e);
}
One could define a class that implemented this interface and then
create an instance of it:
public class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// do something
}
}
...
new MyActionListener()
But frequently, we don't really care what the name of the class is, we only want
to make an instance of it. In that case we can create an instance
of an anonymous class using the following syntax:
new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do something
}
}
This looks as if we are creating an instance of the interface,
but actually we are creating an instance of a class that is never given
a (visible) name. The anonymous class implements the interface and
defines the method actionPerformed.
With Java's graphics model, events are reacted to, rather than detected. In other words, rather than repeatedly asking ``Did someone click my window?'' a Java application program will say ``if someone clicks my window, let me know.'' Then the general event system will call a method when the window is clicked. The object to be notified must implement the required interface.
In our case, we have a few buttons above the window:
addActionListener, for example:
clearButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
doClear();
}
});
The doClear method is a method of the outer class (class
Main) which the anonymous class has implicit access to.
This feature is very convenient and used frequently in Java programs.
Our animation programs are multi-threaded programs because the timer/animation thread is different from the thread that handles updating the screen. Programming for this model requires some careful work. We were sloppy in the last homework, but this homework, you will need to be careful to follow these rules:
In particular, the collection of particles used in the simulation should never change. How then can one add or remove particles? There's a trick! We make a new collection that is a copy of the list of particles, make changes to it (in one thread) and then install it as the (immutable!) list of particles being simulated. The field that holds the list is mutable (and will be marked ``volatile'').
You will need to complete a Main class that creates a gravity
simulation window with four buttons as described above.
In particular, you will need to use the technique described for
updating the collection of particles being simulated without race conditions.
You need to use iterators to do the work.
You need to update the Particle ADT to add a ``_name''
field, update the constructor to take the name, and override the
toString method to print the name and position.
Then the doShow method simply can print the particles, and this
overriding will cause the name and position to be printed.
You need to complete the class ManyParticles
using a collection class, rather than a sequence.
In $CLASSHOME/src/homework3, we provide the
skeleton files for Main.java and ManyParticles.java and
also a JAR files of all unchanged classes you need from earlier
homework assignments,
as well as the
stripped down Collection interface and ArrayList
implementation.
You will also want to get the file in the solution for Homework #1 that
implements the Particle ADT:
$CLASSHOME/solution/1/edu/uwm/cs351/Particle.java.
In your Eclipse project in AFS, you should choose
``Project>Properties,'' and then select ``Java Build Path'' and the
``Libraries'' tab. Then press the button ``Add External Jar'' and use
the file selector to point to $CLASSHOME/src/homework3/ and
then select homework3.jar.
At the deadline, your homework/3/ directory must include