Issue #011
November, 1996
Contents:
Newsletter Index
Java Language Specification
Comparing C/C++ and Java Part 11 - Preprocessing
Introduction to Applet Programming Part 7 - Animation
Performance - Binary Search Class
NEWSLETTER INDEX
An index to all the Java and C++ newsletters can be found on the Web
at:
http://rainbow.rmi.net/~glenm
The index will be updated as new issues come out.
JAVA LANGUAGE SPECIFICATION
This is the name of a recently-published book by Gosling, Joy, and
Steele, published by Addison-Wesley. It's about 800 pages and costs
around $35. There are about 450 pages on the language proper, and 300
on the core packages like java.lang, java.util, and java.io. Included
is a LALR(1) grammar for the language.
This is a good book if you're interested in the exact details of how
the language and associated packages work. It's not a tutorial, and
does go into a lot of depth about particular language features.
COMPARING C/C++ AND JAVA PART 11 - PREPROCESSING
C and C++ have a preprocessor that is run over source files before
other processing. Java does not have a preprocessor.
One use of the preprocessor is to define constants:
#define N 79
In Java this can be accomplished by saying:
public static final int N = 79;
where "public" means that the constant is available to all, "static"
means that it's shared by all object instances of a given class, and
"final" means it cannot be changed after initialization.
Another use of the preprocessor is to define macros:
#define max(x, y) ((x) > (y) ? (x) : (y))
This is typically done for speed or readability. A good compiler
reduces the need for this facility, by inline expanding short
methods. This is an area of Java still in a state of flux, however.
The preprocessor can be used to #include other files into a source
file. Java packages and naming conventions and import directives (see
newsletters #003, #004, and #005) mostly eliminate the need for
#include.
Finally, the preprocessor has directives like:
#ifdef XXX
stuff ...
#endif
to perform conditional compilation, typically on a per-platform
basis. Java is a platform-independent language, and in theory such a
directive is not needed. In practice, however, it would be useful to
be able to do conditional compilation. For example, the AWT (Abstract
Windowing Toolkit), may perform differently across platforms, due to
the vagaries of the underlying window systems.
There's nothing to stop you from using your own preprocessor or macro
processor, but such an approach is not part of the official Java
language.
INTRODUCTION TO APPLET PROGRAMMING PART 7 - ANIMATION
In previous issues we've talked about the use of basic graphics in a
Java applet, and considered some techniques for the input of text. In
this issue we'll talk about something quite different, namely
animation. This is a technique that can be used to make applets do
"neat" things.
First of all, let's look at the source for an animation applet:
import java.applet.*;
import java.awt.*;
public class Animate extends Applet implements Runnable {
// thread identifier
private Thread an_thread = null;
// Start and Stop buttons
private Button start_button = null;
private Button stop_button = null;
// current state of animation
private int st = 0;
// initialize the applet
public void init()
{
start_button = new Button("Start");
stop_button = new Button("Stop");
add(start_button);
add(stop_button);
}
// handle mouse actions
public boolean action(Event e, Object arg)
{
if (e.target == start_button) {
start();
return true;
}
else if (e.target == stop_button) {
stop();
return true;
}
else {
return super.action(e, arg);
}
}
// start the applet
public void start()
{
if (an_thread == null) {
an_thread = new Thread(this);
an_thread.start();
}
}
// stop the applet
public void stop()
{
if (an_thread != null && an_thread.isAlive())
an_thread.stop();
an_thread = null;
st = 3;
}
// run a thread
public void run()
{
for (;;) {
// get graphics for the applet window
Graphics g = this.getGraphics();
try {
switch (st++) {
case 0:
g.setColor(Color.red);
g.fillOval(25, 35, 250, 250);
break;
case 1:
g.setColor(Color.yellow);
g.fillOval(125, 135, 150, 150);
break;
case 2:
g.setColor(Color.blue);
g.fillOval(225, 235, 50, 50);
break;
case 3:
g.clearRect(0, 0, 300, 300);
st = 0;
break;
}
// sleep for a second
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
}
}
}
along with the HTML code that drives the applet:
Interface to Animation Applet
We've seen parts of the applet code before, for example the graphics
that draws ovals (actually circles in this example), the init()
method, the setting up of buttons, and so on. This particular
animation draws three circles of different sizes and colors, and then
repeats itself.
What's different in this example is the use of threads. A thread,
which also is called names like "lightweight process" and "task", is a
distinct execution of Java code that is taking place at a given time.
A program or applet may use threads to allow multiple streams of code
to execute simultaneously.
Normally a Java applet responds to events such as mouse clicks or
keyboard input. But we'd like this animation applet to do something
continuously without waiting for events, so we create a thread and
start it running. The lines:
an_thread = new Thread(this);
an_thread.start();
create a thread, specifying a reference for a class object that
implements the Runnable interface (that is, defines a method run()).
This method is executed as the "body" of the thread. In the case at
hand, the method simply checks the current state and draws the
appropriate circle or else clears the window in preparation for
starting another cycle.
We've set up a couple of Start and Stop buttons, tied to start() and
stop() methods in the applet. If Stop is selected, the thread
execution stops, and Start will restart the animation by reestablishing
the thread.
Threads are an important part of Java about which we will say more in
future issues.
PERFORMANCE - BINARY SEARCH CLASS
As we've discussed previously, there are still some issues around the
performance of Java, and thus there is a premium on the use of
efficient algorithms.
One such algorithm is the familiar one of binary search, where a
sorted list is searched by continually halving the search area until
the desired element is found or it is determined that the element is
not in the list.
In Java this might look like:
import java.util.Vector;
public class Search {
// no one should instantiate this class
// since it exists only as a packaging vehicle
// for the static method search()
private Search() {}
public synchronized static int search(Vector v, Object objp,
Orderable op)
{
if (v == null || objp == null || op == null)
throw new IllegalArgumentException("null arg");
int low = 0;
int high = v.size() - 1;
while (low <= high) {
int mid = (low + high) / 2;
int c = op.compareTo(objp, v.elementAt(mid));
if (c < 0)
high = mid - 1;
else if (c > 0)
low = mid + 1;
else
return mid;
}
return -1;
}
}
where an index 0 <= index < N is returned, or -1 if the element is not
found. The Vector class found in Java does not automatically maintain
a sorted order for the items in the vector.
This algorithm is straightforward save for the notion of an
Orderable. What is this? An Orderable is an interface:
public interface Orderable {
public int compareTo(Object p1, Object p2);
}
If a given class implements an interface, that means that it defines
the methods of the interface. This is the method of choice at the
moment for passing a method reference as an argument, or in C/C++
terms, passing a pointer to a function. In other words, we create an
instance of a class that implements the Orderable interface, which
means that the instance will have a compareTo() method that we can
call out to.
To see how this works, consider this example that uses the search
class:
import java.util.*;
class Ord implements Orderable {
public int compareTo(Object p1, Object p2)
{
int n1 = ((Integer)p1).intValue();
int n2 = ((Integer)p2).intValue();
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
else
return 0;
}
}
public class test {
public static void main(String args[])
{
Vector v = new Vector();
int N = 10000;
int i = 0;
for (i = 0; i < N; i++)
v.addElement(new Integer(i));
for (i = 0; i < N; i++)
Search.search(v, new Integer(i), new Ord());
}
}
We create a Vector of 10000 integers, each wrapped in an Integer
wrapper. We then search for each in turn, passing to Search.search()
an object instance of Ord, a class that implements the Orderable
interface and thus is guaranteed to contain a compareTo() method for
comparing two Object references that refer to Integer wrappers.
This approach is somewhat like the bsearch() library function in ANSI
C. A similar technique can be used for sorting. The above search
class is part of a Java class library described on the Web page:
http://rainbow.rmi.net/~glenm/javalib/index.html
ACKNOWLEDGEMENTS
Thanks to Jay Burgess, Thierry Ciot, Irv Kanode, Mike McCann, Mike
Paluka, Srihari Sampathkumar, and Bob Shore for help with proofreading.
SUBSCRIPTION INFORMATION / BACK ISSUES
To subscribe to the newsletter, send mail to majordomo@world.std.com
with this line as its message body:
subscribe java_letter
Back issues are available via FTP from:
rmi.net /pub2/glenm/javalett
or on the Web at:
http://rainbow.rmi.net/~glenm
There is also a C++ newsletter. To subscribe to it, say:
subscribe c_plus_plus
using the same majordomo@world.std.com address.
-------------------------
Copyright (c) 1996 Glen McCluskey. All Rights Reserved.
This newsletter may be further distributed provided that it is copied
in its entirety, including the newsletter number at the top and the
copyright and contact information at the bottom.
Glen McCluskey & Associates
Professional Computer Consulting
Internet: glenm@glenmccl.com
Phone: (800) 722-1613 or (970) 490-2462
Fax: (970) 490-2463
FTP: rmi.net /pub2/glenm/javalett (for back issues)
Web: http://rainbow.rmi.net/~glenm