Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Learn Java from Ben Franklin

Write better Java code using Franklin's learning techniques

In his autobiography (see Resources for a link), Ben Franklin describes how he worked to improve his writing. Franklin found prose he judged to be excellent, wrote a short encapsulation of each sentence's main idea (he called them hints; here I will use the term summaries), put them aside for several days, and then tried to recreate the original using only his hints. He then compared his work with the original, making corrections where he fell short, and sometimes finding that he seemed to have improved on the original. People learning Java can do the same: find a model Java program, briefly summarize each line or section, put the notes away for a while, and then attempt to recreate the original from the notes. Once the program is finished, compare it to the original and make corrections where necessary; perhaps you'll discover you have improved the original program. In this article, I'll provide several exercises for applying Franklin's learning techniques to Java.

Exercise 1: Using summaries

Consider the following demonstration program, which creates a file and writes three lines of text to that file:

import java.io.*;
public class WriteTest2 {
   public static void main(String[] args) {
      try {
         FileWriter fw = new FileWriter("test.txt");
         BufferedWriter bw = new BufferedWriter(fw);
         PrintWriter pw = new PrintWriter(bw);
         pw.println("This is a test");
         pw.println("This is only a test");
         pw.println("In the event of a real emergency it would be too late");          
         pw.close();
         bw.close();
         fw.close();
      }
      catch (Exception e) {
         System.out.println(e.toString());
      }
   }
}        


One way to summarize the text is:

main()
try
FileWriter object
BufferedWriter object
PrintWriter object
Write one lame joke to file
close FileWriter object
close BufferedWriter object
close PrintWriter object
catch


Now you put the notes and original program away for a few days, after which you try to write a program based on the list of summaries. Then you compare your version of the program to the original version. If you see a deficiency in your version, make a note. You may even have the satisfaction of discovering that your version is superior.

While the above code, as well as other example code in this article, is relatively simple, you can use the exercises presented here with much more difficult programs. I chose relatively easy-to-understand programs so that audiences of mixed Java skills could easily grasp them. Rest assured, however, that those with more advanced skills can do these same exercises using more complex Java programs.

Exercise 2: Randomly ordering summaries

Franklin also created an even more challenging exercise: instead of writing the summaries in order, he put them in random order. As with the previous exercise, he would put the notes away for a while, then try to recreate the original from the unordered summaries. Similarly, you can randomize the summary order of Java programs that you will later recreate. For example, you can try to recreate the above program based on the following random list of summaries:

catch
PrintWriter object
close BufferedWriter object
FileWriter object
Write one lame joke to file
close PrintWriter object
main()
BufferedWriter object
close FileWriter object
try


To help create random lists, the following program takes a text file and creates a new file with the original file's lines in random order. The program should be run from the command prompt in the form of "Scrambler file1.ext file2.ext." Here file1.ext is the original file, and file2.ext is the randomized file. If the output file already exists, it will be overwritten without any warning, so take care in choosing an output filename.

import java.io.*;
import java.util.*;
public class Scrambler {
   public static void main(String[] args) {
      if (args.length < 2) {
         System.out.println("Must have two arguments in the form of:");
         System.out.println("Scrambler file1.ext file2.ext");
      }
      else {
         String inputFile = args[0];
         String outputFile = args[1];
         Scrambler sc = new Scrambler();
         sc.scramble(inputFile, outputFile);
      }
   }
   public void scramble(String input, String output) {
      try {
         FileReader     fr = new FileReader(input);
         BufferedReader br = new BufferedReader(fr);
         PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(output)));
         List list = new ArrayList();
         String text;
         text = br.readLine();
         while (text != null) {
            list.add(text);
            text = br.readLine();
         }
         fr.close();
         br.close();
         int x = list.size();
         Collections.shuffle(list);
         for ( int I = 0 ; I < x ; I++) {
            String s = (String) list.get(I);
            System.out.println(s);
            pw.println(s);
         }
         pw.close();
      }
      catch(Exception e) {
         System.out.println(e.toString());
      }
   }
}


If you can understand the general workings of the above program, you may want to make a list of this program's summaries for your own Java learning exercise.

Transforming exercises

Another method Franklin used was to change text to verse (poetry), lay it aside for several days, and then change the verse back to text. You can do similar exercises with Java -- for example, you can:

  • Change applets to applications
  • Change programs that read and write to files from a Reader/Writer model to programs that use InputStream/OutputStream
  • Change threaded applications that subclass Thread to those that create a class that implements Runnable


Exercise 3: Combining declarations

Let's start with a simple example. When creating a chain of input or output streams, you can create separate objects that get chained, as in the first program listing:

         FileWriter fw = new FileWriter("test.txt");
         BufferedWriter bw = new BufferedWriter(fw);
         PrintWriter pw = new PrintWriter(bw);


Alternatively, you can combine all the declarations into one line. One exercise, then, would be to change the first program into one whose chain of output streams is declared in one line. A sample solution is given below:

import java.io.*;
public class WriteTest {
   public static void main(String[] args) {
      try {
         PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("test2.txt")));
         pw.println("This is a test");
         pw.println("This is only a test");
         pw.println("In the event of a real emergency it would be too late");
         pw.close();
      }
      catch (Exception e) {
         System.out.println(e.toString());
      }
   }
}     


Exercise 4: Writer and OutputStream

Another exercise you can do is to change a program that uses the Writer model to one that uses the OutputStream model, yet produces the same output. Then, set the OutputStream model aside for some days before changing it back to a program using the original Writer model. Starting with the version of the program immediately above, you might come up with:

import java.io.*;
public class WriteTest {
   public static void main(String[] args) {
      try {
         DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new
FileOutputStream("test3.txt")));
         dos.writeBytes("This is a test\r\n");
         dos.writeBytes("This is only a test\r\n");
         dos.writeBytes("In the event of a real emergency it would be too late\r\n");         
dos.close();
      }
      catch (Exception e) {
         System.out.println(e.toString());
      }
   }
}


Similarly, you could put this program away for some days before changing it back to the Writer model.

Exercise 5: Extending Thread vs. implementing Runnable

When working with Threads, you can extend Thread or implement Runnable. Therefore, as an exercise, you can transform a program that extends Thread into one that implements Runnable, and vice versa. The simple program below extends Thread and counts down from 5 to 0, waiting one second between each count:

public class ThreadDemo extends Thread {
   public static void main(String[] args) {
      ThreadDemo t = new ThreadDemo();
      t.start();
   }
   public void run() {
      for ( int i = 5 ; i > -1 ; i--) {
         System.out.println(i);
         try {
            sleep(1000);
         }
         catch(InterruptedException e) {
            System.out.println(e.toString());
         }
      }
   }
}


One way to change the above program into one that implements Runnable is shown below:

public class ThreadDemo2 implements Runnable {
   public static void main(String[] args) {
      ThreadDemo2 td = new ThreadDemo2();
      Thread t = new Thread(td);
      t.start();
   }
   public void run() {
      for ( int I = 5 ; I > -1 ; I--) {
         System.out.println(I);
         try {
            Thread.sleep(1000);
         }
         catch(InterruptedException e) {
            System.out.println(e.toString());
         }
      }
   }
}   


As with the previous exercise, you would set your "Runnable" version aside for a few days, then attempt to change it back to a program that extends Thread.

Exercise 6: Applets and applications

An inherently more difficult exercise is to convert applets to applications and back again. Consider the following applet:

import java.applet.*;
import java.awt.*;
public class AppletDemo extends Applet {
   Button button1 = new Button("Button 1");
   Button button2 = new Button("Button 2");
   public void init() {
      add(button1);
      add(button2);
   }
}       


To view the applet on my machine, I used the following HTML code:

<HTML>
<BODY>
<APPLET CODE = "AppletDemo.class" WIDTH=400  HEIGHT=300> </APPLET>
</BODY>
</HTML>


Transforming the applet into an application requires several changes. For the sample answer below, I extended Frame, changed the Frame's layout manager to FlowLayout, added a main() method, and created an inner class to listen for window closings. Obviously, there are other ways to change the above applet into an application, so the program below is not the only correct answer.

1 | 2 |  Next >
Resources
  • Also by Robert Nielsen: