| By Roberto Scaramuzzi | Article Rating: |
|
| January 8, 2005 03:45 PM EST | Reads: |
40,596 |
"Ease of Development" is one of the main focuses in J2SE 5. Accordingly, J2SE 5 introduces several new features designed to simplify the developer's life. If you use these new constructs, your code will become more compact and expressive, hence easier to understand and debug. This article explains how you can use the new features to prevent some silly mistakes, as well as some that are not so silly.
Generics
The Collections framework was introduced in Java 1.2. It provides a set of interfaces and implementations that encapsulate many common data structures, the most common being the List and Map interfaces.
The main drawback of using this well-thought-out framework is that a significant amount of casting is required when extracting elements from a pre-J2SE 5 collection (because the collection necessarily has no knowledge of what kind of elements are stored in it). Listing 1 provides a simple example. In the listing, the line with the cast is clunky. Yet it seems that nothing could go wrong, since the only way to add elements to fileList is through the addFile method, which takes only a string.
However, problems will inevitably surface sooner or later. For instance, assume that two years later, you or another developer decide that it would be a good idea to store actual File objects (instead of their names) in the FileList class.
The addFile method will be changed to read:
The code will compile just fine. Yet, when the customer runs the application, it will crash with a ClassCastException as soon as the listExtensions () method is called. One way to guard against this problem is to wrap each casting operation into some defensive code:
public void addFile (File file) {
fileList.add(file);
}
This will solve the immediate problem, but it has several drawbacks:
while (it.hasNext()) {
Object name = it.next();
if (name instanceof String) {
System.out.println
(getExtension((String)name));
}
}
- The code is now even clunkier (and, consequently, more difficult to maintain).
- There are (potentially) many unnecessary instanceof operations.
- The application will fail silently instead of crashing when a disruptive change in code (such as the one above) occurs. Whether this is a better or worse situation for the customer and the support staff is debatable.
J2SE 5 provides a solution for all of this: collections can now use generics. For instance:
private List <String> fileList = new ArrayList <String> ();
Now, only strings can be added to fileList, and method calls, such as fileList.get(0) and fileList.iterator().next(), will return strings with no casting necessary:
String name = it.next();
If you use generics and try to modify the addFile method, the compiler will flag your attempt to add a File to a List<String>. If you change the declaration of fileList to a List<File>, the compiler will now notice that it.next() returns File and not a string; this will force you to fix the listExtensions method.
Note that this is just one use of generics. One of my other favorites is that since the Comparable interface is now generic, you can write the following code and avoid the boilerplate instanceof/casting code that is common for compareTo method implementations:
Enhanced For Loop
public class Comp implements Comparable <Comp> {
public int compareTo(Comp o) {
....
}
}
Here is a snippet of buggy code (slightly modified from the J2SE 5 release notes):
If you try to run it, it will throw a NoSuchElementException. Can you spot the bug? The problem is that i.next() is being called every time a new card is created, rather than once per suit. As a result, we run out of suits much faster than expected. This is how to fix the loop:
List <Suit> suits = ...;
List <Rank> ranks = ...;
List <Card> sortedDeck = new ArrayList <Card> ();
for (Iterator <Suit> i = suits.iterator(); i.hasNext(); )
for (Iterator <Rank> j = ranks.iterator(); j.hasNext(); )
sortedDeck.add(new Card(i.next(), j.next()));
J2SE 5's new enhanced for loop construct provides a neat solution for this. The nested loop in the above code can be rewritten as:
for (Iterator <Suit> i = suits.iterator(); i.hasNext(); ) {
Suit suit = i.next();
for (Iterator <Rank> j = ranks.iterator(); j.hasNext(); )
Rank rank = j.next();
sortedDeck.add(new Card(suit, rank));
}
What appears to be happening is that the variables suit and rank point (in turn) to the elements of the Lists suits and ranks. Under the hood, the same code as in the fixed loop is being run.
for (Suit suit : suits)
for (Rank rank : ranks)
sortedDeck.add(new Card(suit, rank));
Enhanced for loops can also be used while iterating through arrays. This time, instead of not having to explicitly iterate in your code, you can skip any references to the array indices:
As well as being more compact and easy to understand, the enhanced for construct for arrays prevents common bugs, such as referring to the wrong index in nested loops:
String [] vowels = new String [] {"a", "e", "i", "o", "u"};
for (vowel : vowels) {
System.out.println(vowel.toUpperCase());
}
Enums
boolean isVowel (char c) {
}
int vowel_count = 0;
for (int i = 0; i < words.length; i++) {
String word = words[i];
for (int j = 0; j < word.length(); j++) {
if (isVowel(word.charAt(i)) {
vowel_count++;
}
}
}
C has an enum construct, which in theory allows the developer to define an enumerated type, but in practice does little more than define a bunch of integer constants. In the pre-J2SE 5 world, the most common way to accomplish the same task was to mimic the way C works and write code like this:
public class Card {
// suits
public static final int CLUBS = 0;
public static final int DIAMONDS = 1;
public static final int HEARTS = 2;
public static final int SPADES = 3;
// ranks
public static final int ACE = 1;
public static final int DEUCE = 2;
...
public static final int KING = 13; }
Published January 8, 2005 Reads 40,596
Copyright © 2005 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Roberto Scaramuzzi
Roberto Scaramuzzi is a software engineer at Parasoft. He grew up professionally as a Perl developer, but is now also adept at Java and PHP. Roberto holds a PhD in mathematics.
![]() |
Java Developer's Journal News Desk 01/08/06 04:47:07 PM EST | |||
'Ease of Development' is one of the main focuses in J2SE 5. Accordingly, J2SE 5 introduces several new features designed to simplify the developer's life. If you use these new constructs, your code will become more compact and expressive, hence easier to understand and debug. This article explains how you can use the new features to prevent some silly mistakes, as well as some that are not so silly. |
||||
- Book Excerpt: Introducing HTML5
- It's the Java vs. C++ Shootout Revisited!
- Patterns for Building High Performance Applications
- OpenXava 4.3: Rapid Java Web Development
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Cross-Platform Mobile Website Development – a Tool Comparison
- Write Once Run Anywhere or Cross Platform Mobile Development Tools
- Three Buzzwords That Every CIO Hears but One They Should Listen To
- Immersing into JavaScript Frameworks
- Workday Reportedly Prepping to Go Public
- Book Review: Sams Teach Yourself Java in 24 Hours
- Book Excerpt: Introducing HTML5
- Adobe Sends Flex to the Apache Foundation
- Five Years Waiting for JRE 7: Is It Justified? (Part 1)
- Book Excerpt: Java Application Profiling Tips and Tricks
- i-Technology in 2012: Five Industry Predictions
- It's the Java vs. C++ Shootout Revisited!
- Patterns for Building High Performance Applications
- OpenXava 4.3: Rapid Java Web Development
- The Next Web Architecture
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Is Write Once Run Anywhere Ever Going to Be a Reality?
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- JavaServer Faces (JSF) vs Struts
- The i-Technology Right Stuff
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- What's New in Eclipse?
- i-Technology Predictions for 2007: Where's It All Headed?






















