Home arrow Java arrow Page 6 - 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 and deployment
(Page 6 of 9 )

If you are developing an application using assertions, you should be aware that by default, assertions are not enabled in the virtual machine. To enable all assertions, you need to pass the argument -ea to your virtual machine. If you need to enable assertions on system classes, use the switch -esa. Additionally, there are facilities for enabling assertions on individual packages. You should consult your virtual machine documentation for information on how to do this.

When developing a product, you should always have assertions enabled, as they will help you catch bugs. Also, your QA testers should run a program with assertions enabled since it is their job to figure out how to break your code.

In a production release, the situation is a bit foggier. In the first days of a production product release, you may want to make sure the project runs with assertions enabled. Although you will loose some performance and incur a few crashes, you will be able to detect many errors caught by your assertions. When to turn off the assertions in a production environment is a judgment call that the project manager has to make. There will come a time when you think you have used the assertions enough to catch most of the errors, and performance and stability become the overriding need; after all, assertions do crash your program. At that point, it is time to update your shortcuts and batch files to turn off assertions. When releasing new features, you should employ a similar operating strategy. This will help you catch unexpected bugs.

Unfortunately, there is no way to turn assertions on and off in a running system; however, you can easily find out whether they are on by using the little assertion trick shown here:

  boolean ASSERTIONS = false;
 
assert ASSERTIONS = true;

The assert expression here evaluates to true and will not throw an assertion error at any time. If assertions are enabled, then the code will run and ASSERTIONS will be set to true. If assertions are disabled, then the code won’t be executed and ASSERTIONS will remain false.

Chaining Constructors

One of my personal pet-peeves is duplicated code. Unfortunately, you see a lot of it, especially in the creation of GUI widgets. The problem results from the way these widgets are built. Consider the button class shown in Example 1-6.

Example 1-6. Unchained constructors

  package oreilly.hcj.review;
  public class UnchainedConstructors extends JButton
   
implements ActionListener {
   
public UnchainedConstructors(final String text) {
     
setText(text);
     
String tooltip = new String("A button to show " + text);
     
setToolTipText(tooltip);
    }
    public UnchainedConstructors(final String text, final String tooltip) {
     
setText(text);
     
setToolTipText(tooltip);
    }
   
public UnchainedConstructors(final String text, final String tooltip,
                          final ActionListener listener) {
     
setText(text);
      setToolTipText(tooltip);
      addActionListener(listener);
   
}
  }

Although this code will work, it is wasteful and prone to errors. For example, if you change a line in the constructor that accepts three parameters and forget to make the same change in the other constructors, you would have a button that builds correctly under some circumstances, but fails to build correctly under others. This would lead to a debugging session that wouldn’t be much fun. The symptom of the problem is in the thought, “If I change this in one constructor, I have to remember to change it in the others.” Whenever you hear yourself thinking similar thoughts, you should realize that something is wrong. All of your code dependencies should be in the code, and not in your head. Inevitably, you will forget some of these dependencies during your project. Also, even if you have a photographic memory and perfect recall, the junior programmer working for you won’t be privy to these details and could unintentionally bust the code you had so well thought out. To avoid having to remember these things, you can rewrite the class as shown in Example 1-7.

Example 1-7. Simple chained constructors

  package oreilly.hcj.review;
  public class ChainedConstructors extends JButton 
    implements ActionListener {
 
public ChainedConstructors(final String text){
    this(text, new String("A button to show " + text), null);
  }
 
public ChainedConstructors(final String text, final String tooltip) {
    this(text, tooltip, null);
  }
 
public ChainedConstructors(final String text, final String tooltip,
                          
final ActionListener listener) {
    setText(text);
    setToolTipText(tooltip);
    if (listener != null) {
      
addActionListener(listener);
    }
  }

This code is much better; it chains the constructors so that each delegates to the constructor that takes all parameters. This constructor is referred to as the primary constructor. By using this technique, the code for the other constructors is limited only to what they do differently. This technique relieves you of having to remember to change each constructor if the common code is modified. You chain the constructors via the this() method. This special method allows you to call one constructor from another. It is analogous to using the super() method to construct base classes. The only remaining problem is that you have some rather ugly code as a result of chaining your constructors:

  this(text, new String("A button to show " + text), null);

This code results from the fact that, just like super(), you have to use the this( ) method as the first line in the constructor. I have yet to understand why this limitation is in Java, but it does indeed exist. As a result, some rather annoying problems are introduced. In this case, you were merely building a String object in the call to this( ). However, there are other cases where you will need to do a lot more work before calling the primary constructor. The secret to doing this without the ugliness is via helper methods:

  package oreilly.hcj.review;
  public class ChainedConstructors extends JButton 
    implements ActionListener {
   
public ChainedConstructors(final String text, final boolean showDate) {
      this(text,buildDateToolTip(text, showDate), null);
    }
   
private static String buildDateToolTip(final String text,
                              
final boolean showDate) {
      final StringBuffer buf = new StringBuffer(250);  
      buf.append("A panel to show ");
      buf.append(text);
      if (showDate) {
       
buf.append(" created on ");
        DateFormat df = DateFormat.getInstance();   
        buf.append(df.format(Calendar.getInstance().getTime()));
     }
      return buf.toString();
    }
  }

Here, you create a new static method that manipulates the input to the constructor and returns the tool tip text. Then you use the resulting text as the input to the tooltip parameter of the primary constructor. This constructor helper technique makes your code much cleaner and allows you to chain constructors even when there is complex logic within the constructors. The resulting code is much more stable and easier to maintain.

When using helper methods, it is important that you keep in mind one restriction: the this pointer is not available to the virtual machine at the time of a this( ) or super( ) call. The result of this restriction is that you can’t use any instance-scoped methods on the object being constructed. For example, the following code would be illegal:

  public class ChainedConstructors extends JButton
    implements ActionListener {
    public ChainedConstructors(final Class dataType) {
      this(buildClassText(dataType), dataType.getName(),this);
    }
    
protected String buildClassText(final Class dataType) {
      return dataType.getName().substring(dataType.getName()
                             .lastIndexOf('.') + 1);
    }
  }

In Java, a call such as buildClassText( ) is identical to the call this.buildClassText(). The this reference is assumed unless you explicitly add some other kind of reference, such as an object or a class. In this case, the this pointer is not available yet, so you can’t call instance-scoped methods on this object. In fact, even though the class ChainedConstructors implements ActionListener, you can’t even use the this pointer to pass the object as a listener to itself. If you uncomment the above constructor in the code and try to compile it, you will get the following results:

  >ant -Dexample=oreilly/hcj/review/ChainedConstructors.java compile_example
  compile_example:
   
[javac] Compiling 1 source file to C:\dev\hcj\bin    
    [javac]C:\dev\hcj\src\oreilly\hcj\review\
ChainedConstructors.java:43: cannot
  reference this before supertype constructor has been called
   
[javac] this(buildClassText(dataType), dataType.getName(), this);
   
[javac]      ^
   
[javac] C:\dev\hcj\src\oreilly\hcj\review\
ChainedConstructors.java:43: cannot
  reference this before supertype constructor has been called
   
[javac] this(buildClassText(dataType), dataType.getName(), this);
   
[javac] ^
    [javac] 2 errors

In short, the this pointer is off-limits to all constructor helper methods. Therefore, if you want to declare a helper method, you must make sure that the method is declared static. Since a static method doesn’t have a this pointer and doesn’t need one, the call will work properly. However, keep in mind that instance methods on objects already in scope are completely permissible, as shown here:

  public ChainedConstructors(final Color color) {
   
this(color.toString(), "", null);
  }

In this example, the instance method toString( ) on the color parameter passed to you is legal because it is already in scope.

While using chained constructors, you will come across situations in which you do not want to expose the primary constructor to the user of the class. The solution to this problem is to merely make the visibility of the primary constructor protected. That way, you get the best of both worlds. The constructors will be chained, and you won’t reveal any more about the class than you want to. Although it is unusual to see a class with constructors that have various visibilities, it is quite legal.


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