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"!.

Switching on Object Handles: Follow-up

JavaFAQ Home » Story by Dr. Kabutz Go to all tips in Story by Dr. Kabutz


Bookmark and Share 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.

 Printer Friendly Page  Printer Friendly Page
 Send to a Friend  Send to a Friend

.. Bookmark and Share

Search here again if you need more info!
Custom Search



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