Home arrow Java arrow Page 5 - Java in Review
JAVA

Java in Review


Tired of hearing about the gory syntax details of Java? Keep reading for a more conceptual view of the language, focusing on important issues that deserve more attention than they usually receive. Even an advanced programmer will find useful information in this article. It was excerpted from chapter one of Hardcore Java, edited by Robert Simmons Jr. (O'Reilly, 2004; ISBN: 0596005687).

Author Info:
By: O'Reilly Media
Rating: 4 stars4 stars4 stars4 stars4 stars / 12
June 16, 2005
TABLE OF CONTENTS:
  1. · Java in Review
  2. · Syntax Issues
  3. · Collection iteration with for
  4. · Labels
  5. · Assertions versus exceptions
  6. · Assertions and deployment
  7. · Initialization
  8. · Access Issues
  9. · Common Mistakes

print this article
SEARCH DEVARTICLES

Java in Review - Assertions versus exceptions
(Page 5 of 9 )

One of the most common questions asked about assertions is why you should bother using them when you can perform these checks and indicate errors with exceptions.

First of all, the code doing the check may be far more complicated than a simple check for null. In fact, the body of assertion expressions can easily be as much work for the processor as the body of the method itself. If you use exceptions, then these checks will be performed every time the method is called. In a production system, this can add significant overhead.

On the other hand, with assertions, the virtual machine can be set to ignore the assertions. As a result, their processing time is near zero. In development mode, during testing, or during diagnosis of some nasty problem, you can turn on assertions and figure out the problems. Once the software is stable, you can turn off assertions and gain a performance boost. As a bonus, assertions offer a shorthand that makes your code look more elegant.


Assertions are off by default and have to be turned on manually.

To assert or not to assert

Deciding whether to use assertions or exceptions is a decision that you have to take on a case-by-case basis. Here are some tips that will help you make the right decisions:

  • Donít use assertions to validate parameters of public functions. These functions should throw NullPointerException, IllegalArgumentException, and other relevant exceptions instead. Since public functions will be used by other programmers, you should make sure that they get the right errors if they mess up.

  • Use assertions to check preconditions and postconditions on parameters of protected and private access methods.

  • Donít use assertions to check for software user errors. If you expect the user of your web-based online sales system to enter a 10-digit credit card number and she enters only 9 digits, donít use an assert. Instead, throw IllegalArgumentException. If you use assert, as soon as someone turns off assertions on your servlet container, the checking logic in your system would go away.

  • Use assertions to check parameters and variables for conditions that shouldnít happen. For example, consider the following event handler method:

  package oreilly.hcj.review;
 
public class Assertions {
   
public void mouseClicked(final MouseEvent event){
      Object source = event.getSource();
      assert(source != null);
     
int hc = source.hashCode();
      // ...do code using source
    }
  }

The virtual machine should never pass null as a source for a mouse event. However, just to be sure, the user asserts it. The granularity of assertions that you should use here is something of a judgment call. If you assert everything, you will have to write a lot more code; however, your code will be rock solid.

  • Use assertions to check for invalid code branches. For example, consider the following GUI class:

  package oreilly.hcj.review;
 
public class Assertions {
  package oreilly.hcj.review;
 
import java.awt.event.ActionEvent;
  import javax.swing.JButton;
 
public class SomeGuiPanel {
   
private JButton cancelBtn;
    private JButton noBtn;
    private JButton yesBtn;
   
public void actionPerformed(final ActionEvent event) {
      Object source = event.getSource();
      assert (source != null);
     
if (source == yesBtn) {
        // ...do code
      } else if (source == noBtn) {
        // ...do code
      } else if (source == cancelBtn) {
        // ...do code
      } else {
       
assert false : "Invalid Source " + source.toString();
     
}
    }
  }

In this class, the action handler expects the user to click on one of three buttons. The method doesnít expect there to be any other buttons to which the class is listening. However, if a developer added a new button but forgot to change the handler, there would be an extra button to deal with. On the final else clause, the method checks to make sure there arenít any other buttons by using assert. If the emphasized line is hit, the program will generate an assertion exception. In this case, using assert is much more elegant than using throw.


Some may object that the program should always throw an irrecoverable error at this point regardless of whether assertions are enabled. This is a valid point. However, in a production environment, that is not always a good idea. The accountants using your software wouldnít know what an AssertionError is. Instead, when the program crashes, they are likely to give you an informative bug report such as, ďIt crashed while I was making my finance report. Ē Its better to use assertions so the program can at least limp along if something weird happens. Let the developers and QA people deal with the assertion errors.

  • Donít use an assertion to do any work. Assertions are developer-level errors and shouldnít be used to repair state in the program or perform complex logging. Also, donít forget that if a user runs the program without assertions, the code will be gone. If that code was critical to the functioning of the program, you could be in deep trouble.

  • Donít bother internationalizing assertion error messages. Again, since assertions are developer-level issues, internationalizing them would be a waste of time.

  • Use assertions to check post conditions. If you create a method and expect that it will never to return null to the user, you might write something like the following:

  package oreilly.hcj.review;
 
public class SyntaxIssues {
   
protected Object someHelperMethod() {
     
Object result = null;
     
// ...do some code that sets result.
     
assert (result != null); // check post condition.
     
return result;
    }
  }

In this code, the method checks the return value against a post-condition before returning the value. If the value is still null after all of the work, the assertion will toss an error.

Now that you have a good idea of when to use assert and when not to, apply what you have learned on an actual class:

  package oreilly.hcj.review;
 
import java.awt.event.MouseEvent;
  import java.util.Arrays;
  import java.util.Iterator;
  import java.util.List;
 
public class Assertions {
   
public static void main(final String[] args) {
     
helperParseArgs(args);
     
Iterator iter = System.getProperties()
                          .keySet()
                          .iterator();
      for (String key = null; iter.hasNext(); key = (String)iter.next()) {
        assert (key != null);
        System.out.println(key + "=" + System.getProperty(key));
     
}
    }
   
protected static void helperParseArgs(final String[] args) {
     
assert (args != null);
      assert (!Arrays.asList(args)
                     .contains(null));
     
//
--
      List arglist = Arrays.asList(args);
      Iterator iter = arglist.iterator();
      for (String argument = null;
           
iter.hasNext();
            argument = (String)iter.next()) {
        if (argument.startsWith("-D")) {
         
if (argument.length() < 3) {
            int idx = arglist.indexOf(argument);
            throw new IllegalArgumentException("Argument" + idx
                   
+ " is not a legal property argument.");
          }
         
int valueIdx = argument.indexOf('='); 
          System.setProperty(argument.substring(2, valueIdx),
                         argument.substring(valueIdx + 1));
          
assert (System.getProperty(
          argument.substring(2, valueIdx))
                .equals(argument.substring(valueIdx + 1)));
       
}
      }
    }
  }

In this code, you have a method that parses the arguments to the program and looks for system properties to set. If it encounters an argument such as -Dmy.property=5 on the command line, it will set the system property my.property to the value 5.

The method that does the actual work is a protected helper method that checks the arguments to the method for validity using assertions. You should also note that the second check to the method takes quite a bit of work to accomplish since the list has to go through and see whether there are any nulls in the argument list. At production time, however, this work will be removed by turning off assertions. Inside the for loop, the method doesnít use an assertion if the user gives a bad property name because this is an error made by the user of the program and not by the developers of the program.

Finally, the last assert statement checks that the system property was actually set properly. Notice that this assert does the exact same string manipulation work as the original setting of the system property. Some performance-minded developers may catch on to this fact and get the bright idea to store the key and value at each iteration of the loop, as shown here:

  package oreilly.hcj.review;
 
public class Assertions {
 
for (String argument = null; iter.hasNext(); argument = (String)iter.next()) {
   
if (argument.startsWith("-D")) {
      if (argument.length() < 3) {
       
int idx = arglist.indexOf(argument);
       
throw new IllegalArgumentException("Argument" + idx
                          + " is not a legal property argument.");
      }
      int valueIdx = argument.indexOf('=');
     
String key = argument.substring(2, valueIdx);
     
String value = argument.substring(valueIdx + 1);
      
Sys
ystem.setProperty(key, value);
      assert (System.getProperty(key).equals(value));
    }
  }

Although this will work, it is a bit wasteful. The extra allocations of the key and value variables are needed only if assertions are enabled. If assertions are disabled, then these variables will be used only once. Whether to use variables to store parts of an assertion is a judgment call. If the code that is creating the variable is very long, a variable may be the best bet. If the code is simple, you should just save yourself the extra allocations at production time.


blog comments powered by Disqus
JAVA ARTICLES

- Java Too Insecure, Says Microsoft Researcher
- Google Beats Oracle in Java Ruling
- Deploying Multiple Java Applets as One
- Deploying Java Applets
- Understanding Deployment Frameworks
- Database Programming in Java Using JDBC
- Extension Interfaces and SAX
- Entities, Handlers and SAX
- Advanced SAX
- Conversions and Java Print Streams
- Formatters and Java Print Streams
- Java Print Streams
- Wildcards, Arrays, and Generics in Java
- Wildcards and Generic Methods in Java
- Finishing the Project: Java Web Development ...

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials