.
.
java.sun.com developers.sun.com
.
   View this issue as simple text April 5, 2005    

In this Issue

Welcome to the Core Java Technologies Tech Tips for April 5, 2005. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).

This issue covers:

-Introduction to Autoboxing
-Introduction to Tables with JDesktop Network Components (JDNC)

These tips were developed using the Java 2 Platform Standard Edition Development Kit 5.0 (JDK 5.0). You can download JDK 5.0 at http://java.sun.com/j2se/1.5.0/download.jsp.

This issue of the Core Java Technologies Tech Tips is written by Daniel H. Steinberg, Director of Java Offerings for Dim Sum Thinking, Inc, and editor-in-chief for java.net.

See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.

For more Java technology content, visit these sites:

java.sun.com - The Java technology source for developers. Get the latest Java platform releases, tutorials, newsletters and more.

java.net - A web forum where enthusiasts of Java technology can collaborate and build solutions together.

java.com - The ultimate marketplace promoting Java technology, applications and services.

.
.

INTRODUCTION TO AUTOBOXING

Although the Java programming language is an object-oriented language, it's often the case that when using the language you need to work with primitive types. Before J2SE 5.0, working with primitive types required the repetitive work of converting between the primitive types and the wrapper classes. In this tip, you will see how the new autoboxing feature in J2SE 5.0 handles conversions -- for example, between values of type int and values of type Integer. The tip also discusses some autoboxing-related considerations in determining when two numerical values are equal.

The October 5, 2004 Tech Tip, Formatting Output with the New Formatter discussed a new way to format output that is similar to that of the C language's printf. An example in that tip used the printf() method to print an integral value. Here is a simple example that uses the printf() method:

   public class FormatPrint {
     public static void main(String[] args) {
       System.out.printf("There is only %d thing.", 1);
     }
   }

The signature of the printf() method in the FormatPrint example is:

   printf(String format, Object... args)

The number 1 is a primitive and not an object, so you might think that the line:

   System.out.printf("There is only %d thing.", 1);

should not compile. However autoboxing takes care of the situation by automatically wrapping the integer value in the appropriate wrapper object. In J2SE 1.4 you would have needed to manually wrap the primitive value using something like new Integer(1).

Another example of where automatically converting from a primitive might be useful is when you use the Collections APIs. The collections classes are designed to store objects. Consider the following simple example of storing int values from 0 to 9 in an ArrayList:

   import java.util.ArrayList;

    public class Autoboxing {
      public static void main(String[] args) {
          ArrayList<Integer> list = new ArrayList<Integer>();
          for(int i = 0; i < 10; i++){
             list.add(i);
          }
      }
    }

The comparable program for J2SE 1.4.2 would be the following:

   import java.util.ArrayList;

   public class ManualBoxing {
     public static void main(String[] args) {
        ArrayList list = new ArrayList();
        for(int i = 0; i < 10; i++){
            list.add(new Integer(i));
        }
     }
   }

With ManualBoxing you need to explicitly create the Integer object using list.add(new Integer(i)). Contrast that with Autoboxing, where the int i is autoboxed to an Integer object in the line list.add(i).

Autoboxing works well with other new J2SE 5.0 features. For example, the autoboxing feature allows seamless integration between generic types and primitive types. In the ManualBoxing example, the elements of the ArrayList are of type Object. By comparison, in the Autoboxing example, the elements of list are of type Integer. (For more information about generics, see the Tech Tip Generics.)

Let's extend the Autoboxing example to iterate through the elements in the ArrayList and calculate their sum. Notice that this new version also uses the new J2SE 5.0 enhanced for loop to iterate through the elements.

   import java.util.ArrayList;
   
     public class Autoboxing {
       public static void main(String[] args) {
           ArrayList<Integer> list = new ArrayList<Integer>();
           for(int i = 0; i < 10; i++){
              list.add(i);
           }
           int sum = 0;
          for ( Integer j : list){
            sum += j;
          }
         System.out.printf("The sum is %d.", sum );
       }
     } 

Autoboxing is used in a number of places in the updated Autoboxing example. First, ints are boxed to Integers as they are added to the ArrayList. Then Integers are unboxed to ints to be used in calculating the sum. Finally, the int representing the sum is boxed for use in the printf() statement.

The transparency of the boxing and unboxing makes autoboxing easy to use. However using the autoboxing feature requires some care. In particular, testing for the equality of objects created by autoboxing is not the same as testing for the equality of objects that are not created by autoboxing. To see this, look at the following BoxingEquality class:

   import java.util.ArrayList;
   
     public class BoxingEquality {
       public static void main(String[] args) {
          int i = 2;
          int j = 2;
          ArrayList <Integer> list = new ArrayList<Integer>();
          list.add(i);
          list.add(j);
          System.out.printf("It is %b that i ==j.\n",
                            (i==j)); //(1)
          System.out.printf("It is %b that " +
                            "list.get(0) == list.get(1).\n",
                            list.get(0)==list.get(1)); //(2)
          System.out.printf("It is %b that " +
                         "list.get(0).equals(list.get(1)).",
                         list.get(0).equals(list.get(1))); //(3)
        }
     } 

The first print statement in BoxingEquality compares the equality of the primitives i and j. The second print statement compares the equality of the objects created by autoboxing i and j. The third print statement compares the value of the objects created by autoboxing i and j. You would expect the first and the third print statements to return true, but what about the second? The output from running the BoxingEquality program is:

   It is true that i ==j.
   It is true that list.get(0) == list.get(1).
   It is true that list.get(0).equals(list.get(1)).

Now change the values of i and j to 2000.

   import java.util.ArrayList;

   public class BoxingEquality {
     public static void main(String[] args) {
       int i = 2000;
       int j = 2000;
       // . . .
   }

Save, recompile, and rerun BoxingEquality. This time the results are different:

   It is true that i ==j.
   It is false that list.get(0) == list.get(1).
   It is true that list.get(0).equals(list.get(1)).

The primitives are equal and the values of the boxed ints are equal. But this time the ints point to different objects. What you have discovered is that for small integral values, the objects are cached in a pool much like Strings. When i and j are 2, a single object is referenced from two different locations. When i and j are 2000, two separate objects are referenced. Autoboxing is guaranteed to return the same object for integral values in the range [-128, 127], but an implementation may, at its discretion, cache values outside of that range. It would be bad style to rely on this caching in your code.

In fact, testing for object equality using == is, of course, not what you normally intend to do. This cautionary example is included in this tip because it is easy to lose track of whether you are dealing with objects or primitives when the compiler makes it so easy for you to move back and forth between them.

For more information on autoboxing, see Autoboxing.

.
.

INTRODUCTION TO TABLES WITH JDESKTOP NETWORK COMPONENTS (JDNC)

Think of all the routine, boilerplate code you write to create, configure, and display common Swing components. For instance, consider all the things you need to do to display data in a table. The JDesktop Network Components (JDNC) project aims to make it easier for you to produce rich data-centric Java Desktop clients. In this tip you will use JDNC to read tab-separated data from a file and display it in a table. You will put headings on the columns and select a subset to display. You will then filter the rows to display only those rows that meet a specific condition. Finally, you will sort this list and decorate alternating rows in different colors.

To begin, imagine reading weather data from a text file and displaying it in a JTable that's inside of a JScrollPane. The JScrollPane is inside a JPanel, and the JPanel is inside a JFrame. The March 8, 2005 Tech Tip Printing JTables showed how to do something similar to this. Using JDNC, you could read and display the weather data with the following XML:

   <table>
     <tabularData source="weather.txt"/>
   </table>

In other words, you simply create a table element and specify the location of the file containing the data.

To run the example, download the latest JDNC release from the download page. The latest version is currently 0.7 and requires J2SE 5.0. Download and expand the file jdnc-0_7-bin.zip. For this tip, create a directory named jdncTip and copy in the three jar files from jdnc-0_7/lib (jdnc-0_7-all, jdnc-runner, and jlfgr-1_0). Also copy the file weather.txt from jdnc-0_7/demo/data and put it in the jdncTip directory. Create the following file and save it as table.jdnc in the jdncTip directory. This is essentially the simpleTable.jdnc example that is contained in jdnc-0_7/demo.

   <?xml version='1.0'?>
   <om:resource xmlns:om="http://www.openmarkup.net/2004/05/om"
     xmlns="http://www.jdesktop.org/2004/05/jdnc"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation=
       "http://www.jdesktop.org/2004/05/jdnc schema/ jdnc-1_0.xsd">

     <table>
       <tabularData source="weather.txt"/>
     </table>

   </om:resource>

To run the application you will need to have the three jar files you just copied over in your classpath. You must also specify that your main class is org.jdesktop.jdnc.runner.Application. The name of the jdnc file is passed in as a command-line argument.

On a Unix or Linux machine this command is:

   java -cp jdnc-runner.jar:jdnc-0_7-all.jar:jlfgr-1_0.jar
   org.jdesktop.jdnc.runner.Application table.jdnc

On a Windows computer this command is:

   java -cp jdnc-runner.jar;jdnc-0_7-all.jar;jlfgr-1_0.jar
   org.jdesktop.jdnc.runner.Application table.jdnc

You should see a display of the table containing the weather data.

Simple Table

The column headings in the displayed table are generically referred to as column0, column1, and so on. To display the column headings, you need to provide the entire list of them in order. This is done by adding a metaData element as a child of the tabularData element. You label the columns with a tag such as this:

   <columnMetaData name="ICAO"/>

By default, the contents of the column are treated like strings. For data that is not of type string, you can specify the type using a tag such as this:

   <columnMetaData name="ELEVATION" type="float"/>

The available types are string, float, integer, date, and href. Add metadata elements to the table.jdnc file, so that it looks like this:

   <?xml version='1.0'?>
   <om:resource xmlns:om="http://www.openmarkup.net/2004/05/om"
     xmlns="http://www.jdesktop.org/2004/05/jdnc"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.jdesktop.org/2004/05/jdnc
     schema/jdnc-1_0.xsd">

     <table>
       <tabularData source="weather.txt">
         <metaData>
           <columnMetaData name="ICAO"/>
           <columnMetaData name="STATION"/>
           <columnMetaData name="REGION"/>
           <columnMetaData name="COUNTRY"/>
           <columnMetaData name="ELEVATION" type="float"/>
           <columnMetaData name="LATITUDE" type="float"/>
           <columnMetaData name="LONGITUDE" type="float"/>
           <columnMetaData name="TIMESTAMP"/>
           <columnMetaData name="TEMPERATURE" type="float"/>
           <columnMetaData name="DEWPOINT" type="float"/>
           <columnMetaData name="HUMIDITY" type="integer"/>
           <columnMetaData name="VISIBILITY_QUAL"/>
           <columnMetaData name="VISIBILITY" type="float"/>
           <columnMetaData name="WIND_DIR"/>
           <columnMetaData name="WIND_DEG" type="integer"/>
           <columnMetaData name="WIND_SPEED" type="float"/>
           <columnMetaData name="GUST_SPEED" type="float"/>
         </metaData>
       </tabularData>
     </table>
   </om:resource>

Now your table should appear with the column headers you just provided.

Labeled Table

After you label your columns you can easily specify which ones appear, and the order in which they appear. Create a columns element that contains a column element for each column you want displayed. Here's how you specify a typical included column.

   <column title="Station" binding="STATION"/>

You can also specify the justification of the data. For example, the table would look better if the temperature data was centered. That can be easily accomplished easily like this:

   <column title="&#176;C" binding="TEMPERATURE"
                 horizontalAlignment="center"/>

The title attribute specifies the new heading for the column. In the previous example, no title attribute was specified, so the name you specified in each columnMetaData tag was used. Here is what the table.jdnc file looks like after adding column elements that identify five columns for display, the titles to be displayed for those columns, and justification specifications:

<?xml version='1.0'?>
<om:resource xmlns:om="http://www.openmarkup.net/2004/05/om"
  xmlns="http://www.jdesktop.org/2004/05/jdnc"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation=
    "http://www.jdesktop.org/2004/05/jdnc schema/ jdnc-1_0.xsd">

  <table>
    <tabularData source="weather.txt">
      <metaData>
        <columnMetaData name="ICAO"/>
        <columnMetaData name="STATION"/>
        <columnMetaData name="REGION"/>
        <columnMetaData name="COUNTRY"/>
        <columnMetaData name="ELEVATION" type="float"/>
        <columnMetaData name="LATITUDE" type="float"/>
        <columnMetaData name="LONGITUDE" type="float"/>
        <columnMetaData name="TIMESTAMP"/>
        <columnMetaData name="TEMPERATURE" type="float"/>
        <columnMetaData name="DEWPOINT" type="float"/>
        <columnMetaData name="HUMIDITY" type="integer"/>
        <columnMetaData name="VISIBILITY_QUAL"/>
        <columnMetaData name="VISIBILITY" type="float"/>
        <columnMetaData name="WIND_DIR"/>
        <columnMetaData name="WIND_DEG" type="integer"/>
        <columnMetaData name="WIND_SPEED" type="float"/>
        <columnMetaData name="GUST_SPEED" type="float"/>
      </metaData>
    </tabularData>

    <columns>
      <column title="Station" binding="STATION"/>
      <column title="Country" binding="COUNTRY"/>
      <column title="°C" binding="TEMPERATURE"
              horizontalAlignment="center"/>
      <column title="Wind Direction" binding="WIND_DIR"/>
      <column title="Wind Speed" binding="WIND_SPEED"
              horizontalAlignment="center"/>
    </columns>
  </table>

</om:resource>
Reduced Table

Suppose you only wanted to display the data for Bolivia. You can filter the information by searching for those elements whose COUNTRY has the value Bolivia. To do that, you add a filters tag between the tabularData and the columns element:

   <filters>
     <patternFilter expression="Bolivia"
                    match="caseInsensitive unicodeCase"
                    testColumn="COUNTRY" />
   </filters>

Rerun the application. The table will now display only the twenty-one rows corresponding to Bolivia.

You can click on any column label to resort the table in either ascending or descending order, based on the type for that column. You can also easily sort your data programatically, by adding the following sorter element as a child of the filters element:

   <sorter testColumn="TEMPERATURE" direction="descending"/>

Now the rows will appear from locations in which the temperature is warmest to those for which the temperature is coldest.

As a final touch, color odd rows cyan and even rows light grey by adding the following highlighters tag:

    <highlighters>
      <alternateRowHighlighter oddRowBackground="cyan"
        evenRowBackground="light grey"/>
    </highlighters>

Put all of these together and the table.jdnc file should look like this:

   <?xml version='1.0'?>
   <om:resource xmlns:om="http://www.openmarkup.net/2004/05/om"
     xmlns="http://www.jdesktop.org/2004/05/jdnc"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation=
       "http://www.jdesktop.org/2004/05/jdnc schema/ jdnc-1_0.xsd">

     <table>
       <tabularData source="weather.txt">
         <metaData>
           <columnMetaData name="ICAO"/>
           <columnMetaData name="STATION"/>
           <columnMetaData name="REGION"/>
           <columnMetaData name="COUNTRY"/>
           <columnMetaData name="ELEVATION" type="float"/>
           <columnMetaData name="LATITUDE" type="float"/>
           <columnMetaData name="LONGITUDE" type="float"/>
           <columnMetaData name="TIMESTAMP"/>
           <columnMetaData name="TEMPERATURE" type="float"/>
           <columnMetaData name="DEWPOINT" type="float"/>
           <columnMetaData name="HUMIDITY" type="integer"/>
           <columnMetaData name="VISIBILITY_QUAL"/>
           <columnMetaData name="VISIBILITY" type="float"/>
           <columnMetaData name="WIND_DIR"/>
           <columnMetaData name="WIND_DEG" type="integer"/>
           <columnMetaData name="WIND_SPEED" type="float"/>
           <columnMetaData name="GUST_SPEED" type="float"/>
         </metaData>
       </tabularData>
       <filters>
         <patternFilter expression="Bolivia"
                        match="caseInsensitive unicodeCase"
                        testColumn="COUNTRY"/>
         <sorter testColumn=
           "TEMPERATURE" direction="descending"/>
       </filters>
       <highlighters>
         <alternateRowHighlighter oddRowBackground="cyan"
           evenRowBackground="light grey"/>
       </highlighters>

       <columns>
         <column title="Station" binding="STATION"
               prototypeValue="Santa Cruz / El Trompillo city"/>
         <column title="Country" binding="COUNTRY"/>
         <column title="°C" binding="TEMPERATURE"
               horizontalAlignment="center"/>
         <column title="Wind Dir." binding="WIND_DIR"/>
         <column title="Wind Speed" binding="WIND_SPEED"
               horizontalAlignment="center"/>
       </columns>
     </table>

   </om:resource>

The table displays with striped rows, and the rows are sorted in descending order by temperature.

Sorted Table

For more information about JDNC, see the JDNC project page.

.
.
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.
.
.

IMPORTANT: Please read our Licensing, Terms of Use, and Privacy policies:
http://developer.java.sun.com/berkeley_license.html
http://www.sun.com/share/text/termsofuse.html

Privacy Statement: Sun respects your online time and privacy (http://sun.com/privacy). You have received this based on your email preferences. If you would prefer not to receive this information, please follow the steps at the bottom of this message to unsubscribe.

Comments? Send your feedback on the Core Java Technologies Tech Tips to: http://developers.sun.com/contact/feedback.jsp?category=newslet

Subscribe to other Java developer Tech Tips:

- Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE).
- Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME).

To subscribe to these and other Sun Developer Network publications:
- Go to the Sun Developer Network Subscriptions page, choose the newsletters you want to subscribe to and click "Submit".
- To unsubscribe, go to the subscriptions page, uncheck the appropriate checkbox, and click "Submit".


ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at:
http://java.sun.com/developer/JDCTechTips/index.html


Copyright 2005 Sun Microsystems, Inc. All rights reserved.
4150 Network Circle, Santa Clara, CA 95054 USA.


This document is protected by copyright. For more information, see:
http://java.sun.com/developer/copyright.html


Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks or registered trademarks (http://www.sun.com/suntrademarks/) of Sun Microsystems, Inc. in the United States and other countries.

Sun Microsystems,
Inc.
.
.