Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Easy Learn Java: Programming Articles, Examples and Tips - Page 320


Previous 1060 Stories (530 Pages, 2 Per Page) Next

Switching on Object Handles: Follow-up

Go to all tips in Story by Dr. Kabutz
2001-04-28 The Java Specialists' Newsletter [Issue 017b] - Follow-up

2001-04-28 The Java Specialists' Newsletter [Issue 017b] -
Switching on Object Handles: Follow-up

Author: Dr. Heinz M. Kabutz

JDK version:

Category: Language

You can subscribe from our home page: http://www.javaspecialists.co.za (which also hosts all previous issues, available free of charge Smile

As expected, I received interesting comments as a result of my last newsletter, and more is sure to follow after the long weekend.


Here some comments from someone at EnterpriseDeveloper, makers of the excellent JCertify product for practicing for the SUN Certified Java Programmer Examination:

OK abestos suit man,

I'm more concerned about the encouragement of using exceptions to modify/implement regular program flow.

I just picked up some code from another group where they were doing Exceptions to break out of Whiles, For's, thowing exceptions as a kind of break, ... Not only is it a performance hit, it makes for really "nasty" code.

Perhaps you can put a summary statement on your next issue reminding people that Exceptions are not meant to be used as Loop control / Loop Control flow enhancement. I could see someone putting your switch idea inside a BIG For loop - say a list of 1,000 items, and causing 1,000 exceptions.

Very interesting reading - I always like "pushing the envelope", I'm just somewhat concerned about the influence to those "more dangerous" with such an idea. There is an interpretation among those newer to Java that Exception Handling is good for general Program Flow enhancement ( Loop breaking, break statement replacement, throwing Exceptions within a repeating loop,

Exceptions are very much abused by those coming from the C world, or non OO people coming from C++

My response:

I did some tests and found that the performance wasn't that bad, it was actually better than a list of if-instanceof-elses. Note that I am specifically not constructing a new exception, and the construction of exceptions is what takes the time, as far as I know.

Throwing exceptions to change program flow is VERY bad, I agree 100%. I am intending on sending a follow-up to yesterdays newsletter in which I warn again that you shouldn't do this. Perhaps one of the "dangerous" will say: but I've been doing that for a long time...

His response:

There is some degradation to being in a Try / Catch block, but nothing compared to the creation of an Exception. What do you mean by "Not that Bad" - less than 5% degradation ( tight loop )?

*YOU* may not be creating exceptions when using this, and you are probably interpreting it as "I am only condoning the use of this particular set of lines of code". It may encourage *OTHERS* to continue, or even expand, bad Exception Handling practices. They won't know about the performance cost, and they won't understand this could get "nasty" really fast by extending this concept to other programming practices ( and adding REAL Exceptions ).

But I still like the "pushing the envelope" aspect of that code.


In addition, I've included code for a TransactionType class that has a type id int which can be used in a switch statement. This is not as safe, but "cleaner" to use instead of abusing try. I also included a test for multiple if-instanceof-else which turned out slower, and lastly an implementation of using the strategy pattern, which was the fastest of all.

//: TransactionType.java
public class TransactionType extends Throwable {
  private static int counter = 0;
  private final int id = counter++;
  public final int getId() { return id; }
  private final String name;
  private TransactionType(String name) {
    this.name = name;
  }
  public String toString() { return name; }
  public static class None extends TransactionType {
    public static final TransactionType type = new None();
    private None() { super("None"); }
  }
  public static class ReadUncommitted extends TransactionType {
    public static final TransactionType type =
      new ReadUncommitted();
    private ReadUncommitted() { super("ReadUncommitted"); }
  }
  public static class ReadCommitted extends TransactionType {
    public static final TransactionType type =
      new ReadCommitted();
    private ReadCommitted() { super("ReadCommitted"); }
  }
  public static class RepeatableRead extends TransactionType {
    public static final TransactionType type =
      new RepeatableRead();
    private RepeatableRead() { super("RepeatableRead"); }
  }
  public static class Serializable extends TransactionType {
    public static final TransactionType type =
      new Serializable();
    private Serializable() { super("Serializable"); }
  }
}

Now we have a performance test which investigates the various options. Fortunately, the fastest was using Polymorphism and the Strategy design pattern, as I had hoped:


//: Performance.java
import TransactionType.*;
public class Performance {
  public static void switchOnObject(TransactionType transact) {
    try {
      throw transact;
    } catch(TransactionType.None type) {
    } catch(ReadUncommitted type) {
    } catch(ReadCommitted type) {
    } catch(RepeatableRead type) {
    } catch(TransactionType type) {
    }
  }
  public static void switchOnInt(TransactionType transact) {
    switch(transact.getId()) {
    case 0: break;
    case 1: break;
    case 2: break;
    case 3: break;
    case 4: break;
    default: break;
    }
  }
  public static void switchInstanceof(TransactionType transact) {
    if (transact instanceof None) {
    } else if (transact instanceof ReadUncommitted) {
    } else if (transact instanceof ReadCommitted) {
    } else if (transact instanceof RepeatableRead) {
    }
  }
  public static abstract class TransactionTypeStrategy {
    public abstract void doSomething();
  }
  public static class RepeatableReadStrategy extends

      TransactionTypeStrategy {
    public void doSomething() {}
  }
  public static void main(String[] args) {
    long time = -System.currentTimeMillis();
    for (int i=0; i<1000000; i++) {
      switchOnObject(RepeatableRead.type);
    }
    time += System.currentTimeMillis();
    System.out.println("Switching 1000000 times on objects " +
      time + "ms");

    time = -System.currentTimeMillis();
    for (int i=0; i<1000000; i++) {
      switchOnInt(RepeatableRead.type);
    }
    time += System.currentTimeMillis();
    System.out.println("Switching 1000000 times on ints " +
      time + "ms");

    time = -System.currentTimeMillis();
    for (int i=0; i<1000000; i++) {
      switchInstanceof(RepeatableRead.type);
    }
    time += System.currentTimeMillis();
    System.out.println("Switching 1000000 times using " +
      "instanceofs " + time + "ms");

    time = -System.currentTimeMillis();
    TransactionTypeStrategy strategy =
      new RepeatableReadStrategy();
    for (int i=0; i<1000000; i++) {
      strategy.doSomething();
    }
    time += System.currentTimeMillis();
    System.out.println("Switching 1000000 times using " +
      "Strategy Polymorphism pattern " + time + "ms");
  }
}

Result on my notebook:

Switching 1000000 times on objects 481ms
Switching 1000000 times on ints 40ms
Switching 1000000 times using instanceofs 1012ms
Switching 1000000 times using Strategy Polymorphism pattern 30ms

So, for those where it's not clear yet, please don't use exceptions for ANYTHING except error handling. Don't use them to jump out of loops, do switch statements, or find out what methods you were called from.

Incidentally, in one of my first newsletters (004), I mentioned that I would like to be able to get a stack trace without having to construct an exception. So far, no-one has come up with a solution, but I've found a way which *might* work using JNI.

Regards, until next week...

Heinz


Copyright 2000-2004 Maximum Solutions, South Africa

Reprint Rights. Copyright subsists in all the material included in this email, but you may freely share the entire email with anyone you feel may be interested, and you may reprint excerpts both online and offline provided that you acknowledge the source as follows: This material from The Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please contact Maximum Solutions for more information.

Java and Sun are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Maximum Solutions is independent of Sun Microsystems, Inc.

6558 bytes more | 8 comments | Printer Friendly Page  Send to a Friend | Score: 0
Posted by jalex on Sunday, March 13, 2005 (00:00:00) (2456 reads)

Java: Model-View-Controller (MVC) Structure

Go to all tips in Java Notes by Fred Swartz

Here the same calculator is organized according the the Model-View-Controller (MVC)pattern. The idea is to separate the user interface (the Presentation in the previous example) into a View (creates the display,interacting with the Model as necessary), and Controller (responds to user requests, interacting with both the View and Controller as necessary). The literature on MVC leaves room for a number of variations, but they all follow this basic idea. This model is simple and can be used with simple method calls. If there are more complex interactions (eg, the Model is asynchronously updated), an Observer pattern (listeners) may be required.

Main program

The main program initializes everthing and ties everthing together.

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
// stucture/calc-mvc/CalcMVC.java -- Calculator in MVC pattern.
// Fred Swartz -- December 2004

import javax.swing.*;

public class CalcMVC {
    //... Create model, view, and controller.  They are
    //    created once here and passed to the parts that
    //    need them so there is only one copy of each.
    public static void main(String[] args) {
        
        CalcModel      model      = new CalcModel();
        CalcView       view       = new CalcView(model);
        CalcController controller = new CalcController(model, view);
        
        view.setVisible(true);
    }
}

View

This View doesn't know about the Controller, except that it provides methods for registering a Controller's listeners. Other organizations are possible (eg, the Controller's listeners are non-private variables that can be referenced by the View, the View calls the Controller to get listeners, the View calls methods in the Controller to process actions, ...).

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
 66 
 67 
 68 
 69 
 70 
 71 
 72 
 73 
 74 
 75 
// structure/calc-mvc/CalcView.java - View component
//    Presentation only.  No user actions.
// Fred Swartz -- December 2004

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class CalcView extends JFrame {
    //... Constants
    private static final String INITIAL_VALUE = "1";
    
    //... Components
    private JTextField m_userInputTf = new JTextField(5);
    private JTextField m_totalTf     = new JTextField(20);
    private JButton    m_multiplyBtn = new JButton("Multiply");
    private JButton    m_clearBtn    = new JButton("Clear");
    
    private CalcModel m_model;
    
    //======================================================= constructor
    /** Constructor */
    CalcView(CalcModel model) {
        //... Set up the logic
        m_model = model;
        m_model.setValue(INITIAL_VALUE);
        
        //... Initialize components
        m_totalTf.setText(m_model.getValue());
        m_totalTf.setEditable(false);
        
        //... Layout the components.      
        JPanel content = new JPanel();
        content.setLayout(new FlowLayout());
        content.add(new JLabel("Input"));
        content.add(m_userInputTf);
        content.add(m_multiplyBtn);
        content.add(new JLabel("Total"));
        content.add(m_totalTf);
        content.add(m_clearBtn);
        
        //... finalize layout
        this.setContentPane(content);
        this.pack();
        
        this.setTitle("Simple Calc - MVC");
        // The window closing event should probably be passed to the 
        // Controller in a real program, but this is a short example.
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    void reset() {
        m_totalTf.setText(INITIAL_VALUE);
    }
    
    String getUserInput() {
        return m_userInputTf.getText();
    }
    
    void setTotal(String newTotal) {
        m_totalTf.setText(newTotal);
    }
    
    void showError(String errMessage) {
        JOptionPane.showMessageDialog(this, errMessage);
    }
    
    void addMultiplyListener(ActionListener mal) {
        m_multiplyBtn.addActionListener(mal);
    }
    
    void addClearListener(ActionListener cal) {
        m_clearBtn.addActionListener(cal);
    }
}

The Controller

The controller process the user requests. It is implemented here as an Observer pattern -- the Controller registers listeners that are called when the View detects a user interaction. Based on the user request, the Controller calls methods in the View and Model to accomplish the requested action:


  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
// stucture/calc-mvc/CalcController.java - Controller
//    Handles user interaction with listeners.
//    Calls View and Model as needed.
// Fred Swartz -- December 2004

import java.awt.event.*;

public class CalcController {
    //... The Controller needs to interact with both the Model and View.
    private CalcModel m_model;
    private CalcView  m_view;
    
    //========================================================== constructor
    /** Constructor */
    CalcController(CalcModel model, CalcView view) {
        m_model = model;
        m_view  = view;
        
        //... Add listeners to the view.
        view.addMultiplyListener(new MultiplyListener());
        view.addClearListener(new ClearListener());
    }
    
    
    ////////////////////////////////////////// inner class MultiplyListener
    /** When a mulitplication is requested.
     *  1. Get the user input number from the View.
     *  2. Call the model to mulitply by this number.
     *  3. Get the result from the Model.
     *  4. Tell the View to display the result.
     * If there was an error, tell the View to display it.
     */
    class MultiplyListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            String userInput = "";
            try {
                userInput = m_view.getUserInput();
                m_model.multiplyBy(userInput);
                m_view.setTotal(m_model.getValue());
                
            } catch (NumberFormatException nfex) {
                m_view.showError("Bad input: '" + userInput + "'");
            }
        }
    }//end inner class MultiplyListener
    
    
    //////////////////////////////////////////// inner class ClearListener
    /**  1. Reset model.
     *   2. Reset View.
     */    
    class ClearListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            m_model.reset();
            m_view.reset();
        }
    }// end inner class ClearListener
}

Model

The model in indepenent of the user interface. It doesn't know if it's being used from a text-based, graphical, or web interface. This is the same model used in the presentation example.

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
// structure/calc-mvc/CalcModel.java
// Fred Swartz - December 2004
// Model
//     This model is completely independent of the user interface.
//     It could as easily be used by a command line or web interface.

import java.math.BigInteger;

public class CalcModel {
    //... Constants
    private static final String INITIAL_VALUE = "0";
    
    //... Member variable defining state of calculator.
    private BigInteger m_total;  // The total current value state.
    
    //============================================================== constructor
    /** Constructor */
    CalcModel() {
        reset();
    }
    
    //==================================================================== reset
    /** Reset to initial value. */
    public void reset() {
        m_total = new BigInteger(INITIAL_VALUE);
    }
    
    //=============================================================== multiplyBy
    /** Multiply current total by a number.
    *@param operand Number (as string) to multiply total by.
    */
    public void multiplyBy(String operand) {
        m_total = m_total.multiply(new BigInteger(operand));
    }
    
    //================================================================= setValue
    /** Set the total value. 
    *@param value New value that should be used for the calculator total. 
    */
    public void setValue(String value) {
        m_total = new BigInteger(value);
    }
    
    //================================================================= getValue
    /** Return current calculator total. */
    public String getValue() {
        return m_total.toString();
    }
}

5134 bytes more | 8 comments | Printer Friendly Page  Send to a Friend | Score: 5
Posted by jalex on Saturday, March 12, 2005 (00:00:00) (5930 reads)

Previous 1060 Stories (530 Pages, 2 Per Page) Next

530| 529| 528| 527| 526| 525| 524| 523| 522| 521| 520| 519| 518| 517| 516| 515| 514| 513| 512| 511| 510| 509| 508| 507| 506| 505| 504| 503| 502| 501| 500| 499| 498| 497| 496| 495| 494| 493| 492| 491| 490| 489| 488| 487| 486| 485| 484| 483| 482| 481| 480| 479| 478| 477| 476| 475| 474| 473| 472| 471| 470| 469| 468| 467| 466| 465| 464| 463| 462| 461| 460| 459| 458| 457| 456| 455| 454| 453| 452| 451| 450| 449| 448| 447| 446| 445| 444| 443| 442| 441| 440| 439| 438| 437| 436| 435| 434| 433| 432| 431| 430| 429| 428| 427| 426| 425| 424| 423| 422| 421| 420| 419| 418| 417| 416| 415| 414| 413| 412| 411| 410| 409| 408| 407| 406| 405| 404| 403| 402| 401| 400| 399| 398| 397| 396| 395| 394| 393| 392| 391| 390| 389| 388| 387| 386| 385| 384| 383| 382| 381| 380| 379| 378| 377| 376| 375| 374| 373| 372| 371| 370| 369| 368| 367| 366| 365| 364| 363| 362| 361| 360| 359| 358| 357| 356| 355| 354| 353| 352| 351| 350| 349| 348| 347| 346| 345| 344| 343| 342| 341| 340| 339| 338| 337| 336| 335| 334| 333| 332| 331| 330| 329| 328| 327| 326| 325| 324| 323| 322| 321|
320
| 319| 318| 317| 316| 315| 314| 313| 312| 311| 310| 309| 308| 307| 306| 305| 304| 303| 302| 301| 300| 299| 298| 297| 296| 295| 294| 293| 292| 291| 290| 289| 288| 287| 286| 285| 284| 283| 282| 281| 280| 279| 278| 277| 276| 275| 274| 273| 272| 271| 270| 269| 268| 267| 266| 265| 264| 263| 262| 261| 260| 259| 258| 257| 256| 255| 254| 253| 252| 251| 250| 249| 248| 247| 246| 245| 244| 243| 242| 241| 240| 239| 238| 237| 236| 235| 234| 233| 232| 231| 230| 229| 228| 227| 226| 225| 224| 223| 222| 221| 220| 219| 218| 217| 216| 215| 214| 213| 212| 211| 210| 209| 208| 207| 206| 205| 204| 203| 202| 201| 200| 199| 198| 197| 196| 195| 194| 193| 192| 191| 190| 189| 188| 187| 186| 185| 184| 183| 182| 181| 180| 179| 178| 177| 176| 175| 174| 173| 172| 171| 170| 169| 168| 167| 166| 165| 164| 163| 162| 161| 160| 159| 158| 157| 156| 155| 154| 153| 152| 151| 150| 149| 148| 147| 146| 145| 144| 143| 142| 141| 140| 139| 138| 137| 136| 135| 134| 133| 132| 131| 130| 129| 128| 127| 126| 125| 124| 123| 122| 121| 120| 119| 118| 117| 116| 115| 114| 113| 112| 111| 110| 109| 108| 107| 106| 105| 104| 103| 102| 101| 100| 99| 98| 97| 96| 95| 94| 93| 92| 91| 90| 89| 88| 87| 86| 85| 84| 83| 82| 81| 80| 79| 78| 77| 76| 75| 74| 73| 72| 71| 70| 69| 68| 67| 66| 65| 64| 63| 62| 61| 60| 59| 58| 57| 56| 55| 54| 53| 52| 51| 50| 49| 48| 47| 46| 45| 44| 43| 42| 41| 40| 39| 38| 37| 36| 35| 34| 33| 32| 31| 30| 29| 28| 27| 26| 25| 24| 23| 22| 21| 20| 19| 18| 17| 16| 15| 14| 13| 12| 11| 10| 9| 8| 7| 6| 5| 4| 3| 2| 1|


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy