|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
These tips and cautions will help you write better programs and save you from agonizing over why the compiler produces error messages.
The next time you start InstallAnywhere, its startup window takes you to the Advanced Designer.
GLA.EXE installer.
Last month, I asked you to rewrite Lines.java to remove all static analysis violations. Here is my solution:
/**
Lines.java
*/
import java.awt.*;
import java.applet.Applet;
/**
Lines.class describes the Lines applet.
@invariant
*/
public class Lines extends Applet implements Runnable
{
private int width = 0, height = 0;
private Thread runner = null;
private final static int MAXCOLORS = 256;
private final static int SLEEPMILLIS = 50;
/**
Initialize the applet.
@pre
@post
*/
public void init ()
{
// Acquire the applet's width and height.
width = getSize ().width;
height = getSize ().height;
}
/**
Start the applet.
@pre
@post
*/
public void start ()
{
// If no thread exists, create a Thread object that associates with the
// current Lines object, and start a new thread that invokes the current
// Lines object's run() method.
if (runner == null)
{
runner = new Thread (this);
runner.start ();
}
}
/**
Paint the next animation frame.
@pre
@post
@param
*/
public void paint (Graphics g)
{
// Generate a random color and establish that color as the Graphics
// context's drawing color.
Color c = new Color (rnd (MAXCOLORS), rnd (MAXCOLORS), rnd (MAXCOLORS));
g.setColor (c);
// Generate a random set of coordinates in the upper-left quadrant of
// the drawing surface, and use those coordinates as the starting
// coordinates for a new line.
int x1 = rnd (width / 2);
int y1 = rnd (height / 2);
// Compute the line's ending coordinates by mirroring the starting
// coordinates in the lower-right quadrant.
int x2 = width - x1;
int y2 = height - y1;
// Draw the line.
g.drawLine (x1, y1, x2, y2);
// Draw an inverse of the line (for symmetry).
g.drawLine (x1, y2, x2, y1);
}
/**
Return a random number from 0 through limit-1.
@pre
@post
*/
static int rnd (int limit)
{
// Return a random integer that ranges from 0 through limit-1.
return (int) (Math.random () * limit);
}
/**
Run animation loop.
@pre
@post
*/
public void run ()
{
// Obtain a reference to the thread that was started in the applet's
// start() method.
Thread current = Thread.currentThread ();
// As long as runner contains the same reference, keep looping. The
// reference in runner becomes null when the applet's stop() method
// executes.
while (current == runner)
{
// Invoke the paint(Graphics g) method to draw another
// randomly-colored and randomly-positioned line.
repaint ();
// Pause for SLEEPMILLIS milliseconds to achieve an eye-pleasing
// display.
try
{
Thread.sleep (SLEEPMILLIS);
}
catch (InterruptedException e)
{
System.err.println ("Thread was interrupted.");
}
}
}
/**
Stop the applet.
@pre
@post
*/
public void stop ()
{
// Tell the line-drawing thread to terminate.
runner = null;
}
/** The following method is overridden to prevent the drawing surface from
being automatically cleared after a line is drawn. Stay tuned to Java
101 to learn more about this method.
@pre
@post
@param
*/
public void update (Graphics g)
{
paint (g);
}
}
Note the various Design by Contract tags (such as @pre). After solving initial static analysis violations, the absence of those tags led to additional violations. As you can see,
I did not have to state actual contracts, just the tags. In practice, you should specify actual contracts (such as @pre g != null).
Read more about Tools & Methods in JavaWorld's Tools & Methods section.