This is an historical document, describing the evolution of Java in its first few revisions. This article should not be consulted for up-to-date information on Java best practices. It was published 2004-07-28 by O’Reilly Media; non-trivial updates in [square brackets].

What’s new? That’s a loaded question. Back in the days of Java 1.0 and 1.1, a Java geek could comfortably claim to "know all about Java." By the time of 1.2, that claim was manifest nonsense. By the time of 1.3 or 1.4, James Gosling started recommending other Java books that he wished he’d seen years earlier. Now that 1.5 is here, if someone says they know all about Java, forget it.

So what’s new, really? J2SE 1.4 introduced a variety of technologies, such as a standardized Java implementation of regular expressions (see Chapter 4 of the Java Cookbook, 2nd Edition). J2SE 1.5 introduces lots more. One of the most notable sets of additions is "generic types," such as collections, that are defined to hold objects of a certain type rather than just Object (obviating the downcast otherwise needed each time you get an object back from a collection), built-in support for typesafe enumerations, and an extended for loop to iterate over collections. For example, with a List of Strings, prior to 1.5 you might write:

List myList = new ArrayList();
myList.add("hello");
myList.add("goodbye");

// myList.add(new Date()); This would compile but cause failures later

Iterator it = myList.iterator();
while (it.hasNext()) {
		String s = (String)it.next();
		System.out.println(s);
}

In 1.5 you can write this as:

List<String> myList = new ArrayList<String>();
myList.add("hello");
myList.add("goodbye");

// myList.add(new Date()); This won't compile!

Iterator<String> it = myList.iterator();
while (it.hasNext()) {
		String s = it.next();	// Look Ma, no downcast!
		System.out.println(s);
}

This mechanism is called "generics" because it allows you to write generic classes, the arguments and return types of methods of which are specified when the class is instantiated.

While the original definition of the List interface and the ArrayList class had methods dealing in java.lang.Objects, in 1.5 these types have been changed to a Generic type so that you can declare and instantiate them with any object type (String, Customer, Integer), and get the benefits of stronger type checking and elimination of downcasts.

Not just these types, but all of the Collections API and most of the other parts of the standard Java API in 1.5 have been updated to be generic types. If you write your own multipurpose classes, you can fairly easily change them to be generics in the same fashion.

The notation <type> is used to specify the particular type with which the class is to be instantiated. Java developers had better get comfortable with this notation, as it is used extensively in the 1.5 JavaDoc!

These additions related to data structuring are all covered in Chapter 8 of my Java Cookbook, 2nd Edition; this chapter is online here.

So what else is new? Well, plenty more, it turns out. And not just in J2SE 1.5. The rest of this article covers a variety of new Java features, and ends with a wrap-up of ways to stay current on Java.

J2SE 1.5 Threading

Java was the first mainstream language with explicit support for multithreading. It has always been possible to write Java applications that run multiple sections of code more or less concurrently. In fact, even the simplest Java application creates at least one thread — Java’s memory allocation garbage collection runs in a background thread, started by the Java runtime before you can say "Hello World."

However, the code required has sometimes been slightly convoluted. In Java 1.5, the API has been significantly expanded to provide a series of utility classes that make it much easier to support multithreaded applications. Even such complex operations as various types of locking, and creation of thread pools, have been addressed. This work is an outgrowth of an open source library developed by Doug Lea, author of the book Concurrent Programming in Java and a computer science professor at State University of New York in Oswego, New York. This code was contributed to the Java Community Process where it has been extensively worked over by a multitasking committee of multithreading experts. The package java.util.concurrent and its subpackages contain all of the new classes, and there are quite a few of them.

One of the key differences from traditional Java synchronization is that the new classes really are concurrent. That is, while a synchronized class such as Vector or Hashtable uses the object’s monitor lock to block all but a single thread from running any synchronized method at a time, the new concurrent classes will allow multiple threads to access them at the same time, yet still provide "thread-safe" access. For example, the new ConcurrentHashMap class allows an unlimited number of concurrent reading threads and a (settable) maximum number of writes. This will generally lead to much better scalability and faster performance, both of which become important when designing enterprise-scale application services. What’s also nice about the ConcurrentHashMap is that, because it still implements the Map interface from java.util, it is a drop-in replacement for the older synchronized Hashtable class. So using it can be as simple as adding an import and changing:

Map myMap = new Hashtable();

to

Map myMap = new ConcurrentHashMap();

Of course, since you read the opening paragraphs, you’ll know that you probably want to use it in a typesafe way, so if your Map were hashing from String to CustomerAddress object, you’d actually write:

Map<String,CustomerAddress> myMap =
	new ConcurrentHashMap<String,CustomerAddress>();

I did say you have to get used to that <type> notation. Note that in 1.5, the Map interface is now declared as Map<K, V> (for Keys and Values); the iteration methods are declared in the interface as Enumeration<K> keys() and Collection<V> values(). So you would get Enumeration<String> keys() and Collection<CustomerAddress> values() from the "keys" and "values" methods, respectively.

Since you give the type for the keys and values when you instantiate a class implementing Map, you get back the iterators with the correct types built in, meaning no downcast needed when you extract the elements.

Getting the JDBC Out of Java

One of the funnier phrases used in Java web development is "getting the Java out of the JavaServer Pages" — putting the Java into reusable components and also making the remaining HTML-like pages easier to maintain.

Hibernate and JDO are two alternative ways of storing data.

They are two of a number of "object-relational mapping" packages that have surfaced in recent years to simplify, as the name implies, the mapping from objects to a relational database. It’s been said that when all you have is a hammer, everything looks like a nail. Similarly, if all you have is JDBC, everything looks like, well, SQL. Hibernate and JDO let you think directly in terms of objects, instead of having to work through the "foreign language" of SQL.

Hibernate is an open source project, available free in source code form from hibernate.org. JDO is an open specification from the Java Community Process (jcp.org). There are many implementations of JDO, both free and commercial; you can find out about many of these at jdocentral.com.

[JPA is an official Java standard, very similar to Hibernate. JPA defines a set of annotations for mapping between Java and the database; Hibernate recognizes these and, in fact, its API is approaching convergence with JPA.]

In Java Cookbook, I felt I had to choose between JDO and Hibernate, so I used JDO in the examples there. [Obviously a bad choice, in hindsight.] To make up for that, I’ll give an example of Hibernate, simplified for presentation purposes from a client-specific login module I wrote for XPlanner (a good tool for XP management, by the way).

import java.util.Date;

import org.hibernate.HibernateException;
import org.hibernate.Session;

import demo.hibernate.ThreadSession;
import demo.domain.Person;
import demo.domain.RoleAssociation;

public class HiberDemo {
	private static final int ROLE_VIEWER = 0;

	public void addPerson() {
		Session sess = null; // Hibernate session, not Http, nor Mail, nor ...

		sess = ThreadSession.get();
		sess.beginTransaction();

		Person person = new Person();

		person.setName("Some Name");
		person.setEmail("some_name@ersatz.dom");
		person.setPhone("555-555-5555");
		person.setPassword("this password is not used");
		person.setLastUpdateTime(new Date());

		sess.save(person);

		//  group roles
		System.out.println("Person.id set to " + person.getId());
		sess.save(new RoleAssociation(0, person.getId(), ROLE_VIEWER));

		sess.flush();
	}
}

What’s interesting is the lack of SQL. [Hibernate handles generation of SQL for us. Any SQL exceptions will be caught and re-mapped to the unchecked HibernateException, making it easier to do error reporting closer to the user in a multi-tier application.]

Of course, there is an XML file that describes the mapping from the fields of the Person class into columns of an SQL table. In fact, you can write this XML file and have Hibernate generate the Person class, if you like! [Modern Hibernate practice specifies the mappings via annotations rather than XML].

And there is also the usual properties file with such details as the JDBC URL and driver.

Hibernate, like JDO and like Entity EJB, provides a high-level, SQL-like query language, as well.

To learn the working details of Hibernate, please check out https://hibernate.org. Another resource is O’Reilly’s Hibernate: A Developer’s Notebook.

Take a look at [JPA] and Hibernate, and you’ll never view JDBC in quite the same light again.

printf is Back

In the early days of Java, it was common for people to try to bring the C-language printf functionality to Java. Most of these attempts worked only for certain cases, and were not really object-oriented approaches. After much complaining from developers and much internal debate, Sun has relented and included printf functionality into J2SE 1.5.

The functionality is contained in the new java.util.Formatter class (not to be confused with the existing DateFormat, NumberFormat, etc., classes) and is also available in convenience routines in System.out (actually, in the PrintStream and PrintWriter classes). The format codes are more comprehensive than the original C printf, but the basic idea is the same: you pass a format string and one or more objects to be formatted according to the format string. For example, you might write:

System.out.print("Pi is approximately %1$6.4f\n", Math.PI)

The % is the lead-in to the format code; the 1$ means it is to format the first argument after the format code (the value Math.PI), and the 6.4f is the same as it was in printf and in Fortran before that — a floating point value with a field-width of six and four digits after the decimal place. So the program prints:

Pi is approximately 3.1416

There is much more to this, with support for date formatting, localization, and more. See the documentation for java.util.Formatter for details.

Oh, and did I mention that there is also scanf-like functionality, in java.util.Scanner? This does not use % format codes, but uses a variety of next() methods, such as next(String), next(Pattern), nextInteger, nextDouble, and so on, plus all of the corresponding hasNext() methods. See the documentation for java.util.Scanner. Also, printf and scanf are covered (including examples) in recipes 10.3 and 10.4 of Java Cookbook, 2nd Edition.

IDEs

Ever since the early days of Java, developers have had many IDEs from which to choose. Today, there are several commercial ones and two major open source ones, both of which are from big companies and both of which are used in the companies' commercial IDEs. Sun’s NetBeans is the open source version of their various Studio products, including the new Creator tool for building JSF-based web sites. And Eclipse is the open source version of IBM’s WebSphere developer products.

At least, it started out that way. But sometimes things take on a life of their own. Both NetBeans and Eclipse have done so, leading to NetBeans.org and the Eclipse Foundation.

Both NetBeans and Eclipse are good developer tools. Eclipse does seem to have the edge in developer momentum. A quick search on Amazon.com, for example, shows a dozen or so Java books with Eclipse in the title and only one with NetBeans in the title. However, NetBeans has a more mature GUI builder (surprisingly, Eclipse’s GUI builder is still in beta as I write this). Eclipse has grown quickly, in part, because it seems to do more to encourage development of plugins. And the recent release of Eclipse 3.0 promises to bring some stability to the IDE, after a number of rapid changes over the last few "milestone builds."

So if Eclipse is somehow better, should Sun throw in the towel? No way! Because, as OpenBSD founder Theo de Raadt says of operating systems, "Choice is good." This is certainly true in IDEs as well. But If I Had to Pick One

I’ve long been fond of using a text editor (vi) and command-line Java. I shunned the early Java IDEs because of stability problems in some (one which shall remain nameless, but was nicknamed Visual Crashé), because of "version lag" (it took most of the IDE vendors a long time to move from 1.1 to 1.2, because of the new event model, just as it is taking them a while to upgrade to 1.5 because of the compiler changes) and — in the early days — the blazing lack of speed.

Most of these things have changed, and so recently, I took up the tools again, trying both NetBeans 3.6 and Eclipse 3.0. I was pleasantly surprised by the productivity gains they offered. I settled on Eclipse because of a project at one of my major clients and because of the number of books available.

I have found moving to Eclipse to be very worthwhile. An IDE is a great place to "encapsulate" all of those finger-twisters for which Java is becoming noted. Eclipse features a lot of shortcuts. For example, to convert a List into an Array, you probably know that (at least in 1.4) you have to call the toArray method, pass in an array of the right length, and cast the result back. In Eclipse, you can just type, for example, newArray = toArray and hit the Completion sequence (Ctrl-Space); and the IDE will fill in:

newArray = (type[]) collection.toArray(new type[collection.size()])

Also, it positions the cursor on type and highlights it, so you can just type, say, String — and it will change it both places. Then you hit the Tab key to move to collection, and type the collection’s name, say, myList, and you are finished. You now have:

newArray = (String[]) myList.toArray(new String[myList.size()])

And that’s just from one shortcut — there are many others defined. To see the shortcuts that are defined, as well as to create your own, go to the Preferences Window, then Java, Editor, and then Templates. Eclipse also has powerful code completion and correction features. For example, if you type File f = new File(someFileName); and you haven’t imported the File class from java.io, you’ll get an error. But rather than making you wait until you run the compiler or Build Project, Eclipse will immediately highlight the error in red at the left margin, and also underline the references to the File class.

eclipse1
Figure 1. Eclipse highlights the error

Just press Ctrl-1 and Eclipse will open a small context menu, one of whose choices is "Import File (java.io)".

eclipse2
Figure 2. Eclipse lets you fix the error quickly

Once you do that, the code compiles nicely.

eclipse3
Figure 3. Eclipse lets you fix the error quickly

And once you save the file, there is no separate compile step! Eclipse builds the class file dynamically while you are editing it, and when you save, it saves both the Java form and the bytecode form. So once you’ve dealt with all of the red (and, hopefully, yellow) icons, and saved your file, you’re finished; time to head out for a decaf latte!

When you get back from coffee, you’ll want to check out Eclipse’s JUnit integration, which is also excellent. Eclipse will build test cases on demand; just give it the name of the class to test. If the class exists, Eclipse will offer you a list of methods for which to write test methods. If not, write your test methods and get Eclipse to generate the methods in the class being tested — great for test-first development! Eclipse will build and re-build your test case dynamically, letting you keep local changes but also maintaining the list of tests to run from Eclipse’s GUI.

Especially if you’ve always been a command-line junkie like me, I recommend that you give Eclipse or NetBeans a fair trial. Download Eclipse or NetBeans (not over a 56K dialup connection) or order them on CD. Pick up one of several good books on Eclipse (including O’Reilly’s Eclipse), and learn your way around, including how to configure options, how to use the error handling and code completion, and "organize imports." Check out the Refactor menu. Then try importing one of your projects, or start a new project, and build some code. Give it a try and I think you’ll like it.

Aspects of Java

One of the key things you should probably try to learn about is a whole new area including lightweight frameworks and the Inversion of Control (IoC) pattern (also called Dependency Injection), and Aspect-Oriented Programming (AOP).

IoC itself is used by many frameworks — it basically means that the framework calls your code instead of vice versa.

Lightweight frameworks such as PicoContainer and the Spring framework go further and allow various components to be constructed automatically, with information being passed (or "injected") into the objects, either by "Constructor Injection" or "Setter Injection." Aspect-Oriented Programming is a way of applying "aspects" — things that don’t fit well into the method-based design of objects — to your code.

The Spring framework is both a light-weight framework and an AOP toolkit; another AOP package is AspectJ. See this ONJava article on AOP in Spring, which has links to more information on Spring and AOP. Keeping Ahead of the Curve

Keeping Up with the Java Joneses

I’ve talked about some of the new technologies happening in the Java world. There are so many; how is a busy developer to keep up with all the changes? I hope this article has helped. The O’Reilly site ONJava.com is a good resource, and O’Reilly Java books are the thing to have on your bookshelf (or your virtual bookshelf, if you prefer to read them on Safari). Don’t forget the Sun/O’Reilly site java.net.

Producer’s Note: Today Safari and CIGNEX Technologies, Inc. have announced that they have created an Eclipse plugin that will allow Eclipse users to search Safari content from within the Eclipse environment. It currently works with Eclipse version 2.1.3 and will soon be available in version 3.0. The plugin and source code are available as a project in the Java Tools Community on java.net: safarieclipse.dev.java.net.

Other resources include JavaWorld.com, Sun’s Java Developer Center (and in particular, their JDC Tech Tips Newsletter), and technology-specific resources such as TheServerSide.com, which specializes in server-side Java.

While it’s not the place for leading-edge technology, The Java Lobby is a good place to keep up on general happenings. There are several forum sites where you can ask questions and get answers on specific Java technologies; these include Java Ranch (founded by O’Reilly author Kathy Sierra) and jGuru.com.

If you still have any free time, there are Java blogs out there. If you want to skim, most of these resources have RSS feeds (if you’re not up on RSS, think of it as "headlines with links;" O’Reilly’s Meerkat was one of the leading early adopters of RSS). Even James Gosling has written an RSS reader, and Mac fans will have RSS support in Safari in Mac OS 10.4 (codenamed "Tiger," the same codename that Sun used for J2SE 1.4).

And, of course, you can always get the newest version of my Java Cookbook to have recipes on most of the features discussed in this article, as well as all the common APIs that were in Java before, such as date & time, number formatting, and many more.

There is no shortage of new technologies, and no shortage of ways to try to keep abreast of and make sense of it all.

Ian F. Darwin has worked in the computer industry for ages: with Unix since 1980, Java since 1995, and OpenBSD since 1998. He is the author of several O’Reilly books, Checking C Programs with lint and Java Cookbook, and co-author of Tomcat: The Definitive Guide with Jason Brittain. [Also Android Cookbook].

In June, 2004 O’Reilly Media, Inc., released Java Cookbook, 2nd Edition. [The Fourth Edition was released in March, 2020].

  • Sample Chapter 8: "Data Structuring with Generics, foreach, and Enumerations (JDK 1.5)," was available free online.

  • You can also look at the Table of Contents, the Index, and the full description of the book.

  • For more information, or to order the book, click here.