20-CS-694 Advanced Programming Techniques Spring 2012
Exceptions for control

Interfaces, Exceptions, Graphics, Animation, Threads, Reflection, Networking, RMI, JDBC, JNI

       Previous     Next     Applet Source     All lectures

Add Up Exception for control

The interface Variable has changed: its checkit() method no longer returns a boolean and, instead, throws an Up exception. Accordingly, the Up class is defined, without state, to extend the Exception class. The checkit() method catches an Up exception from its Choose object: this is what keeps the loop going until it ends and, when that happens, checkit() throws an Up to the next higher level. By using Up we can define method assert_() in the Evaluate class: if an expression evaluates to 0 (false), an Up is thrown by assert_(). This allows all control statements to be removed from checkit() in Evaluate which is significant because, except for solve(), that is the method that a user will have to change for every different problem this approach is going to be used to solve.

Two improvements can be made right away to the code below. If we only want one result instead of all results we can define an Out exception class and raise that exception when a solution is found. The Out object will then be passed right up to the top, bypassing all the intermediate catch blocks which are looking for Up exceptions. The second improvement is to remove the v() and abstract_() methods from the Evaluate class. The abstract_() method will be needed to solve any problem like this so let's put it in a Puzzle class and extend from that. We might as well put the v() in there too to get it out of the way. This is done on the next slide.

   import java.awt.*; 
   import java.awt.event.*; 
   import javax.swing.*; 
   import java.applet.*;
   interface Variable { void checkit() throws Up;  int v();  }
   class Up extends Exception { }
   class Choose implements Variable {
      Variable next_for;
      int val = 0;
      Choose (Variable next_for) { this.next_for = next_for; }
      public void checkit () throws Up {
         for ( ; val < 2 ; val++) try { next_for.checkit(); } catch (Up up) { }
         val = 0;
         throw new Up();
      public int v() { return val; }
   class Evaluate implements Variable {
      Variable i,j,k;
      D problem;
      public Evaluate (D problem) {  
         this.problem = problem; 
         problem.out.append("\nSolve: ((1-i)*j + i*(1-k) + (1-j)*k)\n\n");
      public void assert_ (boolean e) throws Up { if (!e) throw new Up(); }
      public void checkit() throws Up {
         assert_((((1-i.v())*j.v()+i.v()*(1-k.v())+(1-j.v())*k.v()) % 2) == 1);
         problem.out.append("i="+i.v()+" j="+j.v()+" k="+k.v()+"\n");
         throw new Up();
      public void solve () {
         try {
            k = new Choose(this);
            j = new Choose(k);
            i = new Choose(j);
         } catch (Up up) {}
      public int v() { return 0; }
   public class D extends Applet implements ActionListener {
      JTextArea out;
      JButton button;
      public void init () {
         setLayout(new FlowLayout());
         add(new JScrollPane(out = new JTextArea(16,30)));
         add(button = new JButton("Press Me"));
      public void doit() {
         Evaluate eval = new Evaluate(this);
      public void actionPerformed (ActionEvent evt) {  doit(); }