Thứ Năm, 10 tháng 9, 2009

JDK7 java.util.Objects Utility Methods

In recent weeks, there has been news of various features once proposed for JDK 7 that no longer are slated for this release. Although it is not unusual to reduce the scope of a major software project (including a new version of the Java programming language) as its formal release nears, it can still be somewhat disappointing as the current poll results in Java.net's poll emphasizes.

Fortunately, it is not all bad news in terms of features being dropped from JDK 7. Joe Darcy's recent post What methods should go into a java.util.Objects class in JDK 7? could be the beginning of bringing back some enthusiasm regarding JDK 7. Although the addition of these methods may seem like a minor addition, I have found great benefit in using similar utility-heavy classes such as Collections, Arrays, and even the ubiquitous java.lang.System class.

Darcy's post begins with the sentence:

For JDK 7, I think it is high-time the platform included a class like
java.util.Objects to hold commonly-written utility methods.


I couldn't agree more! I have used several other languages that have similar utility methods collected in a class like this one and I miss these when using Java. It would be a welcome addition.

After listing three ideas (two-argument static equals method, static hash code method that handles null, and compareTo for primitives), Darcy concludes the post with this sentence:

What other utility methods would have broad enough use and applicability to go into a common java.util class?


The last quote implies that we could see some handy utility methods added to a java.util.Objects class that would be generally beneficial to a wide number of Java developers.

It is not difficult to come up with useful methods for a class like this. In fact, the difficulty will be constraining what is added and avoiding abuse of utility classes. We have all probably found ourselves writing certain functions routinely or adding projects such as Apache Commons to our system to provide extremely common functionality not provided by the SDK itself. Adding these most-used methods to a central class within the JDK would be beneficial because we could have standardly available well-tested methods for these most common of functions.

Besides our own experience developing homegrown methods, the most obvious sources of ideas for good candidates for a java.util.Objects class can be gleaned from third-party Java libraries fulfilling the same need (such as Apache Commons and OstermillerUtils). For example, I have blogged previously on some common methods provided by Apache Commons that I really like such as ToStringBuilder and EqualsBuilder and HashBuilder. The Apache Commons class ObjectUtils seems to be particularly useful in providing ideas for a java.util.Objects class.

Another obvious source of ideas includes experience with other languages that support similar functionality in a common object. For example, I have regularly appreciated ActionScript's ObjectUtil class that provides methods such as the toString(Object) method (pretty prints an object's representation even when the provided class does not have its own toString implementation).

Stephen Colebourne has provided a lengthy list of Apache Commons Lang-inspired utility methods in his blog post JDK 7 - Method suggestions. Some other responses to Darcy's original request for ideas include toString, a lessons learned response from developing Google Collections's Objects class, a debug utility class, and another version of Colebourne's post.

Not everyone wants to see this java.util.Objects class added as demonstrated by this post. If you would like to see this utility class added and have some ideas for it, now is your opportunity to recommend generic utility classes that you would like to see in a standard central location.

Thứ Tư, 9 tháng 9, 2009

Inconstant Constants in Java

In their 2009 JavaOne presentation Return of the Puzzlers: Schlock and Awe (PDF), Joshua Bloch and Neal Gafter presented seven more puzzlers and extracted lessons learned from each of these puzzlers and their solutions. These lessons learned include old standbys such as read the documentation, ensure you are calling the correct methods, preferring composition over inheritance, and never call an overridable method from constructor. Not surprisingly, many of the lessons learned also tie into Joshua Bloch's Effective Java recommendations.

One of the interesting nuances of the Java programming language highlighted in this presentation is the concept of constant variables in Java. The presentation highlights three sections of the Java Language Specification (JLS) Third Edition (HTML/PDF): 4.12.4 ("final Variables"), 13.4.9 ("final Fields and Constants"), and 15.28 ("Constant Expression"). Section 4.12.4 ("final Variables") defines and warns about constant variables at the very end of that section (links/references to other sections of JLS omitted; emphasis included in original text):

We call a variable, of primitive type or type String, that is final and initialized with a compile-time constant expression a constant variable. Whether a variable is a constant variable or not may have implications with respect to class initialization, binary compatibility and definite assignment.


The specification and this JavaOne presentation point out that only primitives and String can be constant and that null is not a constant. They also point out problems that can occur between code binaries when constants are inlined and not all code is re-compiled together. For example, if the final keyword is added to a field and the pre-existing binaries try to set the field, an IllegalAccessError will be thrown. Going the other way, removing final behaves the same way as changing the value of a final field: the pre-existing code will not break, but it also won't realize that there is a new value.

This is demonstrated with a simple example. Suppose you have a simple class called Constants as defined below.

Constants.java - First Version

package dustin.examples.puzzlers;

/**
* The main purpose of this class is to demonstrate the problems with inlined
* constants when they are not really constant.
*/
public class Constants
{
public static final String ONE = "Uno";
public static final String TWO = "Dos";
public static final String THREE = "Tres";
public static final String FOUR = null;
public static final String FIVE = "Cinco";
}


Four of the five constants defined above have String values. However, one of them, the constant FOUR, is assigned to null.

Suppose that the Constants.java class was edited or replaced with the code below:

Constants.java - Second Version

package dustin.examples.puzzlers;

/**
* The main purpose of this class is to demonstrate the problems with inlined
* constants when they are not really constant.
*/
public class Constants
{
public static final String ONE = "Un";
public static final String TWO = "Duex";
public static final String THREE = "Trois";
public static final String FOUR = "Quatre";
public static final String FIVE = "Cinq";
}


The second version of this class maps English number names to French names for the same numbers. In this case, all five constants had Strings defined. Now suppose there was a "client" class that makes use of Constants.java with code as shown in the next listing.

NumbersTranslator.java - Client Using Constants.java

package dustin.examples.puzzlers;

import static java.lang.System.out;

public class NumbersTranslator
{
public static void main(final String[] arguments)
{
out.println("One is " + Constants.ONE);
out.println("Two is " + Constants.TWO);
out.println("Three is " + Constants.THREE);
out.println("Four is " + Constants.FOUR);
out.println("Five is " + Constants.FIVE);
}
}


If the above class, NumbersTranslator, was recompiled every time the Constants.java class it depends on was recompiled, we would not see any discrepancies. However, if we compiled NumbersTranslators against the first version (Spanish) of Constants.java and then recompiled only the second version (French) of Constants.java without recompiling NumbersTranslators, an interesting result occurs when we run the NumbersTranslators.main(). That output is shown next.



The interesting observation here is that even though the code was run with the "French version" of Constants.java, four of the five lines printed still show the Spanish versions (from first version of Constants.java file). However, the value printed for the fourth constant is the French version.

This output demonstrates two principles. First, true constant variables are inlined. This is why the Spanish versions of the constants remained for four of five lines remained despite having the French version of Constants.java on the classpath. The fact that the fourth line displayed the French version illustrates the second point: null is not a constant variable and thus is not inlined and so the actual constant on the classpath is used in that case.

The JavaOne presentation and the JLS both recommend the same two practices for dealing with this subtlety. The first recommendation, in this case from the specificaition, is: "The best way to avoid problems with 'inconstant constants' in widely-distributed code is to declare as compile time constants only values which truly are unlikely ever to change." In other words, only designate a field as static final if the field will truly never change. The specific suggests that mathematical constants fit well here. This makes sense because we don't expect these physical constants to change (or will they?). The specification goes further: "Other than for true mathematical constants, we recommend that source code make very sparing use of class variables that are declared static and final."

The second recommendation provided by both the JLS and the JavaOne presentation is to, as the JLS states, "declare a private static variable and a suitable accessor method to get its value." The specification demonstrates this with a code snippet similar to the following:


private static String ONE;
public static int getOne() { return ONE; }


Bloch and Gafter propose a similar concept. They demonstrate a general static ident method that accepts the type of the constant and returns the passed-in parameter. It would look something like this:


private static String ident(String stringConstant)
{
return stringConstant;
}

public static final String ONE = ident("uno");


The reason that both of these related approaches work is that the calling of the respective methods (getXXXX or ident) prevents inlining of the constant variables involved.

The next code listing shows the first version of Constants.java re-written to use the Bloch/Gafter approach.


package dustin.examples.puzzlers;

/**
* The main purpose of this class is to demonstrate the problems with inlined
* constants when they are not really constant.
*/
public class Constants
{
private static String ident(final String stringConstant)
{
return stringConstant;
}

public static final String ONE = ident("Uno");
public static final String TWO = ident("Dos");
public static final String THREE = ident("Tres");
public static final String FOUR = ident(null);
public static final String FIVE = ident("Cinco");
}


The output is shown next. I followed the same steps as before (building and rebuilding only the once-Spanish version of Constants.java file with the new French version), but the results are different (which is better in this case):



As the output shows, the recommended "indent" approach prevents inlining of the constant variables and allows the updated Constants.java constants to be fully reflected in the executed code.

This may not be a big deal in a development environment in which full clean and rebuild processes prevent these binary mismatches, but it has potential to lead to nasty and not-so-obvious bugs in "widely-distributed code" situations described in the specification.


Additional References

Java Constants - A nice post on this subject

Rotten Statics - Nice overview of where this bit a development team "in real life"

Thứ Hai, 7 tháng 9, 2009

Latest on Java Developers' Feelings Regarding Java SE 7

Java.net's current poll question asks, "What's your reaction to the JDK 7 feature list?" The poll is still relatively new, but with nearly 230 responses, the results are already interesting. Currently, eighty percent of the votes come down into three questions that fall into the respective categories of positive, neutral, and negative. The remaining twenty percent of the responses are either "Other" or "I don't care."

Of the responses that fall into one of the three questions that are not "Other" or "I don't care," the current majority has chosen the neutral option of "Some handy buy insignificant features." This is probably what best describes my reaction as well with a little positive and a little negative. Following close behind, the next most popular choice is the outright negative option "Disappointed; when do we get JDK 8?" I definitely feel at least a little this way. The enthusiastically positive response "I love it and can hardly wait" is the third of the three committed responses, but is a little too enthusiastic for me to select.

There are some features I look forward to in Java SE 7 (modularization, Indexing Access Syntax for Lists and Maps [see also my related post], automatic resource management, and improved generics type inference, G1 garbage collector, and VM improvements for better dynamic language support), but some of the features I looked most forward to have been taken out of consideration for Java SE 7 (reified generics, Elvis operator and null safe operators, JMX 2, improved exception handling, BigDecimal operators).

There are several good sources of information on what is coming with Java SE 7. The OpenJDK site hosts a page with JDK 7 Features that categorizes features currently slated for Java SE 7 in categories of Virtual Machine, language, core, client, and Enterprise (the last entails upgrading the JDK's built-in versions of JAXP, JAXB, and JAX-WS to the latest stable releases).

Sun provides the JDK 7 Preview Page with a link to download a preview Java SE 7 SDK and a link to the Java SE 7 API documentation. Alex Miller's Java SE 7 page also provides a useful collection links to blogs and articles related to Java SE 7.

I have not heard of an overarching Java Specification Request (JSR) for Java SE 7 yet, but we already know several of the constituent JSRs that will likely be included:
JSR 203: More New I/O APIs for the JavaTM Platform ("NIO.2")
JSR 292: Supporting Dynamically Typed Languages on the JavaTM Platform
JSR 294: Improved Modularity Support in the JavaTM Programming Language
JSR 296: Swing Application Framework
JSR 308: Annotations on Java Types

Java Arrays: Copying, String Representations, and Collections

Since the introduction of the Java Collections Framework with JDK 1.2, I have used Java arrays significantly less frequently than I used to. However, I still use arrays occasionally, often because a library or API I am using makes heavy use of arrays. When working with arrays, the Arrays class can be particularly helpful. In this posting, I'll look at how this class simplifies the copying of arrays and providing String representation of arrays. I'll also look at how the use of the method Collection.toArray(T[]) is often used to access the first element of a Java collection without explicit iterating.


Copying Arrays

As demonstrated in the Arrays section of the Java Tutorials, the System class provides an arraycopy method that can be used to copy the contents from one array into another.

The method below shows use of System.arraycopy to copy an entire source array to a destination array. The parameters to this method allow for various ranges of the original array to be copied to the target array.


/**
* Copies the contents of the provided array into a new array that this method
* returns to the caller. This method is implemented with System.arraycopy.
*
* @param originalArray Array to be copied.
* @return Copy of the provided array.
*/
public static String[] copyCompleteStringArrayOldFashionedWay(final String[] originalArray)
{
final int originalArraySize = originalArray.length;
String[] destinationArray = new String[originalArraySize];
System.arraycopy(originalArray, 0, destinationArray, 0, originalArraySize);
return destinationArray;
}


This method works fine, but I prefer to use one of the overloaded Arrays.copyOf or Arrays.copyOfRange methods for copying array contents. I'll look briefly at my reasons for preferring the approach after demonstrating their use. The following method shows copying an entire array using Array.copyOf.


/**
* Copies the contents of the provided array into a new array that this method
* returns to the caller. This method is implemented with Arrays.copyOf.
*
* @param originalArray Array to be copied.
* @return The copy of the provided array.
*/
public static String[] copyCompleteStringArrayNewFangledWay(final String[] originalArray)
{
return Arrays.copyOf(originalArray, originalArray.length);
}


The several overloaded versions of Arrays.copyOf were introduced with Java SE 6. This is just one of the many advances Java SE 6 has brought to Java development and I have covered several of them in this blog.

As the code snippets above demonstrate, the Arrays.copyOf approach results in leaner, more concise code than use of System.arraycopy. Perhaps most important in this difference in terms of required code is that Arrays.copyOf and Arrays.copyRange do NOT require the developer to pre-allocate memory for the array that is the destination of the copying procedure. This may seem like a minor thing, but it reduces the possibility of running into a NullPointerException or other problem associated with improper sizing of the destination array. This appeals to me and my general aversion to unnecessary NullPointerExceptions.

Another thing that I prefer about use of Arrays.copyOf or Arrays.copyRange over System.arraycopy is the location (class) in which these utility methods are found. Functionality for copying arrays just feels out of place in the System class while array copying seems a perfect fit for the Arrays class. The Arrays class's Javadoc-based documentation starts with this sentence in its class-level comments: "This class contains various methods for manipulating arrays (such as sorting and searching)." Copying of arrays seems to fit naturally here and, in fact, I think adding "copying" to "sorting and searching" in the Javadoc sentence would be appropriate.


Printing Contents of Arrays

Once one gets used to easily printing the contents of a Java Collection (or Map) by passing that Collection (including Map in this context of "Collection") to System.out, System.err, or other stream, it can be a little bit disappointment to return to what is printed out for an array when trying to do the same thing. To illustrate, the code snippet below shows methods for printing the contents of an array, of a List, of a Set, and of a Map. Although they all look very similar in code, the output for the array is quite different from that of the Collections.


/**
* Print contents of provided Array directly to standard output using
* System.out directly.
*
* @param array Array to be printed directly to standard output with
* System.out.
*/
public static void printStringArrayDirectly(final String[] array)
{
out.println(INDENT + "DIRECT: " + array);
}

/**
* Print the provided List of Strings to standard output.
*
* @param stringsToPrint List of Strings to be printed.
*/
public static void printStringList(final List<String> stringsToPrint)
{
printHeader("List Directly (" + stringsToPrint.getClass().getCanonicalName() + ")");
out.println(INDENT + stringsToPrint);
}

/**
* Print the provided Set of Strings to standard output.
*
* @param stringsToPrint Set of Strings to be printed.
*/
public static void printStringSet(final Set<String> stringsToPrint)
{
printHeader("Set Directly");
out.println(INDENT + stringsToPrint);
}

/**
* Print the provided Map of Strings to Strings to standard output.
*
* @param stringsToPrint Map of String to String to be printed.
*/
public static void printStringMap(final Map<String,String> stringsToPrint)
{
printHeader("Map Directly");
out.println(INDENT + stringsToPrint);
}


The output for the Map, Set, and List appear in a reasonable and readable output format. The arrays's output is not nearly so readable or useful. Instead, it looks something like [Ljava.lang.String;@42e816. This output does tell us that it is an array of Strings and that its "unsigned hexadecimal representation of the hash code" (see Object.toString Javadoc for more on this) is 42e816 for this particular array instance.

One option for printing the contents of an array is to iterate over the array explicitly and print each element as iteration occurs over that element. Fortunately, an easy convenience method (Arrays.toString()) was added to the previously discussed Arrays class in J2SE 5 to make printing of array contents easier. This is demonstrated in the next code snippet.


/**
* Print contents of provided Array directly to standard output using
* System.out with results of Arrays.toString() handling of provided array.
*/
public static void printStringArrayUsingArraysToString(final String[] array)
{
out.println(INDENT + "ARRAYS'S TOSTRING: " + Arrays.toString(array));
}


As shown in the above code snippet, it is easy to invoke Arrays.toString on the array. In fact, it is an overloaded method that supports arrays of all of the primitive types as well as general objects as used in this example. The output of this static method is strikingly similar to the output when a List of Strings is printed directly.

Although my preference is to use Arrays.toString to print contents of an array, another approach one could take is to first convert the array to a Collection and then take advantage of the fact that Collections are converted to a readable String format implicitly. This is done with another static Arrays method, Arrays.asList(). This method directly provides a List based on a provided array. If a Set is desired, the resultant List can be passed to the constructor of a Set implementation that accepts a Collection as a parameter (such as HashSet).


Using Arrays to Retrieve Specific Element of Collection

Although I predominately use collections today rather than arrays, there are times when array syntax is highly useful. A common example of this is when I need to access a specific element in a collection. This seems to occur for me mostly when in a situation in which I know there is only one element in the collection and I need to access it directly. I don't want to iterate over the collection to simply obtain the first element. An easy way to get this first element without explicit iteration over the collection is to use the toArray methods on List and Set to first get an array handle to the elements underlying the collection and then to access the element by array index. The following code shows how this can be done. As noted in the comments, Java arrays employ C-like zero-based indexes and so using an index of 0 obtains the first element.


/**
* Extract the first element from the provided List of Strings. This is
* accomplished by using List's toArray method to access the List as an
* array and then the first element of that array is simply accessed with
* zero for the index (zero-based arrays means zero is index of first element
* in array).
*
* @param list List of Strings from which to extract first String element.
* @return First String element of the provided List of Strings.
*/
public static String extractFirstStringElementFromList(final List<String> list)
{
return list.toArray(new String[0])[0];
}

/**
* Extract the first element from the provided Set of Strings. This is
* accomplised by using Set's toArray method to access the Set as an array
* and then the first element of that array is simply accessed with zero for
* the index (zero-based arrays means zero is index of first element in array).
* WARNING: 'Order' in a Set is a tricky business. The use of the "first
* element" of a Set is probably mostly useful in situations where the calling
* code happens to know that the Set is a single element Set, perhaps because
* it is returned from a call using Collections.singleton().
*/
public static String extractFirstStringElementFromSet(final Set<String> set)
{
return set.toArray(new String[0])[0];
}


Of course, the array syntax allows any element in the Collection-turned-array to be accessed with the integer representing the array index. I just used zero here for the first element because it is the case I most commonly run into. It is also worth noting that List.get(int) already allows one to easily access a specific element in the List (my preferred approach). There is no similar method for Set presumably because this often doesn't make any sense in a Set context because some Set implementations (most notably HashSet) do not have the "predictable iteration order" of the LinkedHashSet.

I have stated previously that I'm a little disappointed with the list of features that appear to have made it into Java SE 7. However, it is interesting to see that it Index Access for Syntax for Lists and Maps appears on its ways into Java SE 7.


Conclusion

The Arrays class makes use of arrays in Java more convenient and easier than direct manipulation of those arrays. In this blog post, I have focused on use of overloaded Java SE 6 methods Arrays.copyOf (and corresponding Arrays.copyRange), J2SE 5's overloaded Arrays.toString() methods, and the Arrays.asList() method. I include the complete class containing above code snippets below.


Example Code - JavaArrays.java


package dustin.examples;

import static java.lang.System.out;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* This class demonstrates some Java utility functions related to Java arrays.
*/
public class JavaArrays
{
/** New line/carriage return/form feed. */
private static final String NEW_LINE = System.getProperty("line.separator");

/** Represents tab or indentation for output. */
private final static String INDENT = "\t";

/**
* Copies the contents of the provided array into a new array that this method
* returns to the caller. This method is implemented with System.arraycopy.
*
* @param originalArray Array to be copied.
* @return Copy of the provided array.
*/
public static String[] copyCompleteStringArrayOldFashionedWay(final String[] originalArray)
{
final int originalArraySize = originalArray.length;
String[] destinationArray = new String[originalArraySize];
System.arraycopy(originalArray, 0, destinationArray, 0, originalArraySize);
return destinationArray;
}

/**
* Copies the contents of the provided array into a new array that this method
* returns to the caller. This method is implemented with Arrays.copyOf.
*
* @param originalArray Array to be copied.
* @return The copy of the provided array.
*/
public static String[] copyCompleteStringArrayNewFangledWay(final String[] originalArray)
{
return Arrays.copyOf(originalArray, originalArray.length);
}

public static Map<String, String> generateMapToUppercase(final Collection<String> keys)
{
final Map<String, String> map = new HashMap<String, String>();
for (final String key : keys)
{
map.put(key, key.toUpperCase());
}
return map;
}

/**
* Extract the first element from the provided List of Strings. This is
* accomplished by using List's toArray method to access the List as an
* array and then the first element of that array is simply accessed with
* zero for the index (zero-based arrays means zero is index of first element
* in array).
*
* @param list List of Strings from which to extract first String element.
* @return First String element of the provided List of Strings.
*/
public static String extractFirstStringElementFromList(final List<String> list)
{
return list.toArray(new String[0])[0];
}

/**
* Extract the first element from the provided Set of Strings. This is
* accomplised by using Set's toArray method to access the Set as an array
* and then the first element of that array is simply accessed with zero for
* the index (zero-based arrays means zero is index of first element in array).
* WARNING: 'Order' in a Set is a tricky business. The use of the "first
* element" of a Set is probably mostly useful in situations where the calling
* code happens to know that the Set is a single element Set, perhaps because
* it is returned from a call using Collections.singleton().
*/
public static String extractFirstStringElementFromSet(final Set<String> set)
{
return set.toArray(new String[0])[0];
}

/**
* Print contents of provided Array directly to standard output using
* System.out directly.
*
* @param array Array to be printed directly to standard output with
* System.out.
*/
public static void printStringArrayDirectly(final String[] array)
{
out.println(INDENT + "DIRECT: " + array);
}

/**
* Print contents of provided Array directly to standard output using
* System.out with results of String.valueOf() handling of provided array.
*/
public static void printStringArrayUsingStringValueOf(final String[] array)
{
out.println(INDENT + "STRING'S VALUEOF: " + String.valueOf(array));
}

/**
* Print contents of provided Array directly to standard output using
* System.out with results of Arrays.toString() handling of provided array.
*/
public static void printStringArrayUsingArraysToString(final String[] array)
{
out.println(INDENT + "ARRAYS'S TOSTRING: " + Arrays.toString(array));
}

/**
* Print provided array to standard output using several different mechanisms
* of accessing String contents of array.
*
* @param array Array to be printed.
* @param label Label to be printed above printed array contents.
*/
public static void printStringArray(final String[] array, final String label)
{
printHeader(label);
printStringArrayDirectly(array);
printStringArrayUsingStringValueOf(array);
printStringArrayUsingArraysToString(array);
}

/**
* Print the provided List of Strings to standard output.
*
* @param stringsToPrint List of Strings to be printed.
*/
public static void printStringList(final List<String> stringsToPrint)
{
printHeader("List Directly (" + stringsToPrint.getClass().getCanonicalName() + ")");
out.println(INDENT + stringsToPrint);
}

/**
* Print the provided Set of Strings to standard output.
*
* @param stringsToPrint Set of Strings to be printed.
*/
public static void printStringSet(final Set<String> stringsToPrint)
{
printHeader("Set Directly");
out.println(INDENT + stringsToPrint);
}

/**
* Print the provided Map of Strings to Strings to standard output.
*
* @param stringsToPrint Map of String to String to be printed.
*/
public static void printStringMap(final Map<String,String> stringsToPrint)
{
printHeader("Map Directly");
out.println(INDENT + stringsToPrint);
}

/**
* Print the single provided String along with a header using the provided
* label.
*
* @param stringToPrint String to be printed.
* @param label Label to be used in header printed with this String.
*/
public static void printSingleString(final String stringToPrint, final String label)
{
printHeader(label);
out.println(INDENT + stringToPrint);
}

/**
* Prints provided label String as part of simple header to standard output.
*
* @param label Label to be included in header.
*/
public static void printHeader(final String label)
{
out.println(NEW_LINE);
out.println(
"====================================================================");
out.println("===== " + label + " ======");
out.println(
"====================================================================");
}

/**
* Main function for running demonstrations of Java array utility functions.
*
* @param arguments Command-line arguments; none expected.
*/
public static void main(final String[] arguments)
{
// Use fruits-oriented String array to demonstrate copying of arrays with
// System.arraycopy. Will also demonstrate multiple ways to print array.
final String[] fruitsSourceArray =
{"Apple", "Banana", "Grape", "Orange", "Strawberry", "Tomato", "Watermelon"};
final String[] fruitsDestinationArray =
copyCompleteStringArrayOldFashionedWay(fruitsSourceArray);
printStringArray(fruitsSourceArray, "Fruits SOURCE Array");
printStringArray(fruitsDestinationArray, "Fruits DESTINATION Array");

// Use vegetables-oriented String array to demonstrate copying of arrays
// with Arrays.copyOf. Will also demonstrate multiple ways to print array.
final String[] vegetablesSourceArray =
{"Asparagus", "Broccoli", "Carrot", "Green Bean", "Pea", "Spinach", "Tomato"};
final String[] vegetablesDestinationArray =
copyCompleteStringArrayNewFangledWay(vegetablesSourceArray);
printStringArray(vegetablesSourceArray, "Vegetables SOURCE Array");
printStringArray(vegetablesDestinationArray, "Vegetables DESTINATION Array");

// Demonstrate simplified printing of Java collections
final List<String> fruitsList = Arrays.asList(fruitsSourceArray);
printStringList(fruitsList);
final Set<String> fruitsSet = new HashSet<String>(Arrays.asList(fruitsSourceArray));
printStringSet(fruitsSet);
final Map<String, String> fruitsMap = generateMapToUppercase(fruitsList);
printStringMap(fruitsMap);

// Extract 'first' element of List and Set using toArray
final String firstListElement = extractFirstStringElementFromList(fruitsList);
printSingleString(firstListElement, "First Element from List");
final String firstSetElement = extractFirstStringElementFromSet(fruitsSet);
printSingleString(firstSetElement, "First Element from Set");
}
}

Thứ Ba, 1 tháng 9, 2009

Java's goto

There is an old programmer joke that goes something like this: One programmer in anger says to the second programmer, "Go to Hell!" The second programmer replies in obvious repulsion, "Ugh, you used goto!" The point of this nerdy humor is that to many programmers, use of "goto" is just about the worst offense one can commit.

There are several reasons that the goto is held in such low esteem among software developers. Edsger W. Dijkstra's paper A Case Against the GO TO Statement is a relatively early treatise on the evils of GOTO abuse. In that article, Dijkstra states, "[I became] convinced that the go to statement should be abolished from all 'higher level' programming languages." Dijkstra's Go To Statement Considered Harmful letter not only lambasted the goto statement, but also started a popular computer science trend of using the phrase "considered harmful" (though those two words were apparently used outside of programming before that).

Many programmers since Dijkstra have been bitten by some of the maintainability problems associated with use of goto statements in certain languages. Other programmers have heard these stories or have had the "Thou shalt not use goto" pounded into them so much that they don't need to experience its drawbacks firsthand to believe that they should not use GOTO.

Although the goto statement appears to have a generally bad reputation, it is not without its supporters. Frank Rubin wrote a response to Dijkstra's Go To Statement Considered Harmful (March 1968) called GOTO Considered Harmful' Considered Harmful (March 1987). In that letter, Rubin wrote about Dijkstra's letter having an effect on programmers so dramatic that "the notion that the GOT0 is harmful is accepted almost universally, without question or doubt." Of this observation, Rubin wrote, "This has caused incalculable harm to the field of programming, which has lost an efficacious tool. It is like butchers banning knives because workers sometimes cut themselves." Note that Dijkstra responded to Rubin's letter with On a Somewhat Disappointing Correspondence. The Cunningham & Cunningham Wiki page Go To says this about the goto statement: "The apprentice uses it without thinking. The journeyman avoids it without thinking. The master uses it thoughtfully."

There are numerous other resources that cover the pros and cons of using the goto statement. I don't intend to rehash that debate here other than the brief presentation of the early history of the controversy already covered. I have heard some Java developers stating that Java does not have a goto statement and that is what I want to discuss in the remainder of this blog post.

Java does reserve "goto" as a reserved keyword. However, it is an unused keyword. What this means is that although the keyword does not actually do anything productive, it is also a word that cannot be used in code for names of variables or other constructs. For example, the following code will not compile:


package dustin.examples;

/**
* Class demonstrating Java's goto-like functionality.
*/
public class JavaGotoFunctionality
{
/**
* Main executable function.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
final String goto = "Go to bed!";
}
}


If I try to compile that code, I see an error like that shown in the next screen snapshot.



The error message "<identifier> expected" with a pointer at the space before "goto" gives an experienced Java developer enough of a clue to quickly realize that there is something wrong about using "goto." However, it may not be as obvious to someone new to Java.

I generally do not use the goto construct, but I also recognize that there are situations in which its use makes for code that is more readable and uses less crazy work-arounds than not using it. In Java, this has also been realized and support is provided for some of the most common situations in which a goto statement would be most useful and would likely actually be preferable to alternatives. The most obvious examples of this are the labeled break and labeled continue statements. These are discussed and demonstrated in the Java Tutorials section Branching Statements.

The ability to label a particular statement and then have the break or continue apply to that statement rather than its most immediate statement (as an unlabeled break or continue does) is especially useful in cases where nested loops would otherwise require more code and more complex code to accomplish the same thing. I have found that I can often redesign my data structures and code to avoid such situations, but this is not always practical.

Another good resource related to use of goto-like functionality in Java is the 13 June 2000 JDC Tech Tip Goto Statements and Java Programming. As this tip points out, the labels can actually be used to any block and are not limited to break and continue. However, it is my experience that necessity of this approach outside of break and continue is far less common.

One important observation about labels is that code execution does not literally return to that label when the break somelabel is executed. Instead, execution flow goes to the statement immediately following the labeled statement. For example, if I had an outer for loop called "dustin:", then a break to that would actually go to the first executable statement following the end of that labeled for loop. In other words, it acts more like a "goto the statement following the labeled statement" command.

I don't provide any examples of using these labeled break or labeled continue statements here because there are plenty of good examples easily located online. Specifically, the two resources that I have already mentioned (Java Tutorials Branching Statements and Goto Statements and Java Programming Tech Tip) include simple illustrative examples.

The more I work in the software development industry, the more convinced I become that there are few absolutes in software development and that extremist positions will almost always be wrong at one point or another. I generally shy away from use of goto or goto-like code, but there are times when it is the best code for the job. Although Java does not have direct goto support, it provides goto-like support that meets most of my relatively infrequent needs for such support.

Thứ Hai, 31 tháng 8, 2009

Java News - August 2009 - Java SE 7 and Java-Related Acquisitions

There have been several big news stories related to Java development this month. Several of these stories are sure to have long-term impact on Java developers. These stories include more definitive information on what to expect in Java SE 7 and the continuing consolidation of Java-related companies.

Update on Java SE 7's Project Coin

Project Coin is the aggregation of "small language" changes for Java SE 7. I have blogged about some of the potential features to be added to the Java programming language as part of Project Coin in blog postings such as Small Java 7 Language Changes, Java SE 7 New Features: Latest News, and 2009 JavaOne: Project Coin.

This week, we have learned more information on which small language proposals will be delivered in Java SE 7. Several blog posts have relayed this news and the DZone Top Links currently has the top four links as related to Java SE 7 (three specifically related to the small language changes announcement).



The big announcement of which small language changes will be delivered with Java SE 7 was provided in Joseph D. Darcy's weblog entry Project Coin: The Final Five (or So) (DZone link). Other popular blog postings covering this development include JDK7 Tackles Java Verbosity (DZone/JavaLobby links) and The Seven Small Language Changes that will be in Java SE 7 (DZone link). The last linked post provides additional background detail on some of the implementation progress for the accepted small language changes.

The seven new small language features accepted for inclusion with Java SE 7 are:

1. Switching on Strings

I have written about the lack of Java support for switching on String and on this proposed new Java SE 7 feature. Many other languages have this feature and I have known several developers new to Java who have wondered why it has not been there all along. I feel less interest in it now with the addition of enums in J2SE 5, but it will still be a handy feature to have occassionally.


2. Automatic Resource Management (ARM)

This Joshua Bloch-authored feature proposal is covered thoroughly and relatively succinctly on this Google docs page.


3. Improved Generic Type Inference (Diamond)

I generally like the compile-time type safety provided by Java generics, but there are some ugly things about the generics support. Some improvement in experience with Java generics will be available in Java SE 7 with the generic type inference support. It's not generics reification, but it will still be welcome.


4. Simplified Varargs Method Invocation

Like the improved type inference addition, this new feature will improve developer experience with generics, in this case particularly with mixing generics and varargs.


5. Language Support for JSR 292

This feature is especially attractive to developers who like to use dynamic languages that run on the Java Virtual Machine. JSR 292 is the Java Specification Request called Supporting Dynamically Typed Languages on the Java Platform and the Project Coin portion is specifically related to language support for dynamic languages.


6. Language Support for Collections

In his announcement, Darcy mentions that this accepted Project Coin feature is actually a combination of Collection Literals and Indexing Access Syntax for Lists and Maps. The "Collection Literals" feature would allow for a much more concise and potentially clearer syntax where the Collections class is used today. A main benefit of the "Indexing Access Syntax for Lists and Maps" is the consistent syntax for accessing elements of arrays, Maps, and Lists.


7. Better Integral Literals

Like the last one covered here, this feature is actually a combination of multiple feature proposals. The binary literals proposal and underscores in numbers proposals are the two key proposals Darcy cites as part of this feature.


The Features of Java SE 7

I must confess a little disappointment at the new Java SE 7 small language features from Project Coin. There are some new features that I will be glad to have, but I really wish that Elvis and other null safe operators would have not been voted off the island.

The small features that do appear to be headed for Java SE 7 will be useful and, of course, there are other advancements expected in Java SE 7 of larger magnitude than the Project Coin features such as the improved modularity.

More on the features of Java 7 and a downloadable Java SE 7 preview are available at http://java.sun.com/features/jdk/7/.



SpringSource Acquires and is Acquired

We learned on August 10 that SpringSource was being acquired by VMWare. Just days later, on August 19, we learned that SpringSource had acquired Cloud Foundry.


Terracotta Acquires ehcache

SpringSource was not the only one involved in Java-related mergers and acquisitions this month. We also learned on August 18 that Terracotta has essentially acquired ehcache.


Oracle Acquisition of Sun Approved in United States

The largest Java-related acquisition of the year passed a significant milestone in August with the late August announcement of approval of the Oracle/Sun deal by the United States Department of Justice. The deal also has shareholder approval, but still requires European regulatory approval.

Thứ Năm, 27 tháng 8, 2009

Software Development Bumper Sticker Practices

I loathe bumper stickers. I don't understand what a person is trying to accomplish by defacing his or her vehicle with these bumper stickers. In this blog post I examine how bumper stickers and the misuse of best practices have much in common. This post is not intended to offend owners of bumper stickers - I'm sure that there are people out there with bumper stickers who have them for reasons other than those described here.

I have long been a fan of best practices and rules of thumb that make sense. In fact, I have written three articles on best practices (JSP Best Practices, More JSP Best Practices, and Basic JPA Best Practices). However, as Bill Jackson and many others have pointed out, effective software developers must be willing to think for themselves and deviate from best practices when appropriate rather than blindly adhering to "best practices" at any cost and regardless of circumstances.

A "best practice" that is employed without regard for why it is advantageous and without recognition that things are usually too complicated to always be done "one way" is very likely to end up as a "bumper sticker practice." A "bumper sticker practice" suffers from many of the same problems associated with bumper stickers on vehicles.


Two Sides to Every Story / Trade-offs

Political bumper stickers with pithy statements pushing a position or degrading an opposite position can be particularly irritating and useless. The worst offenders are the bumper stickers that try to boil complex issues down to three to seven words that fit neatly on a bumper sticker.

These types of bumper stickers remind me of the software developer who rigidly applies a "best practice" without really trying to understand if the practice is appropriate or if the particular circumstances reduce the value of the "best practice." For a developer in this example, touting their favorite best practice at every turn might make them feel good about themselves, but that doesn't necessarily make the decision correct. Instead, software development is full of trade-offs in design and implementation and the most effective software developer is able to and willing to look at alternatives to their favorite pet practice.


Pride / Showing Off

It is difficult to think of why a person would place a bumper sticker on his or her vehicle about his or her child being an honor student at such-and-such school except out of a sense of pride. Likewise, it is common to see people place bumper stickers on their vehicles advertising the university they went to (or at least cheer for in athletic events).

It is easy for a developer to fall into the trap of throwing around "best practices" phrases, calling design patterns out by name, and doing similar things in an effort to impress others. Like the bumper stickers, others are often far less impressed with these tactics than the person might believe.


Obsolescence

I have seen bumper stickers for political candidates many years after the particular election to which the stickers applied. I have seen this in cases of both candidates who won the particular election and even candidates who lost that election. I do not really understand why a person would keep a bumper sticker advocating a candidate whose election is won or lost for years after election, but it does happen.

Likewise, a favorite "best practice" can be difficult to shed even if its value is overtaken by advancements and time. The best of the best practices are often relatively timeless and will stand the test of time, but some of the "lesser" best practices are more prone to be the recommended approach one day and fall out of favor compared to new and improved ideas that come along later. The most effective developer is able to continually evaluate "best practices" against current trends and circumstances and is willing to learn new ways to do things. New isn't always better than old, but it is a mistake to not be willing to take advantage of new developments.


Indicative of Aggressive / Forceful Nature

In Bumper Stickers Are Dangerous, Jonah Lehrer cites a study linking increased aggressiveness in driving behavior with owners of bumper stickers. This does not seem particularly surprising, at least in the case of political bumper stickers, because apparently the primary reason for having such stickers is to foist one's opinion on others.

Many of us in the software development community (and I intentionally include myself with "many of us") don't need much encouragement or incentive to have and share our strong opinions with others. I actually have found that strongly opinionated software developers are regularly good at what they do, though being aggressive and overbearing does not always translate to being a good software developer. Any software developer, good or bad, can easily become more aggressive as they defend and throw around their favorite pet practice. I have seen developer who almost seem to want to pick a fight about a favorite practice. I don't understand this mentality whether used with a best practice or applied to a bumper sticker.


Is There Substance Behind the Sticker / Practice?

When I see a bumper sticker expressing a "clever" five word opinion about a particularly complex social, economical, or political concept, I wonder if the owner really understands all the complexities of the issue (or at least understands that they exist because it is difficult for anyone to understand the entire issue) or if they truly believe everything is that simple. My impression is that the owner often lacks the sophistication, knowledge, and life experience to truly understand these complex issues or else he or she would be embarrassed to paste a naive and simplistic bumper sticker on his or her vehicle.

The same can be said for some developers who throw around the latest "best practice" and buzzwords. It is disappointing to find out that in some cases the developer really only has a simplistic view of the problem space. In such cases, he or she does not really understand why a "best practice" is recommended or why it works in most situations or recognize situations in which it is not a best practice.


Inside Information Reduces Effectiveness

I occassionally see a bumper sticker with a phrase or clause for which I don't understand the point being made. My guess is that in many of these cases that it not the effect the owner of the bumper sticker wanted.

The same effect can occur in software development with best practices. In my opinion, a "best practice" is one which most experienced developers would agree is generally the best approach for a particular situation. A practice cannot be a best practice, in my opinion, unless it has been proven and confirmed by a large percentage of experienced developers in a wide variety of circumstances.


Distractions

Bumper stickers can be distracting. Some have text so small that another person who might want to read it must tailgate the vehicle to see it. If there are enough small words crammed onto the sticker, another driver trying to read it might be dangerously distracted. I have found myself somewhat distracted in a slightly reluctant way when I have seen a vehicle completely covered with bumper stickers. Almost like a voyeur, I want to read all of those stickers to see what that person is advertising about himself or herself or to laugh at a particularly clever one. I have often felt that bumper stickers are as bad as any commercial advertising when it comes to being visual pollution.

We should not allow our rush to apply a best practice distract us from doing the difficult but necessary work of truly understanding a problem and considering the alternatives to satisfying that problem. We want best practices to help us improve our software rather than clouding our judgement and polluting our decision-making ability.


Letting Others Think For Us

One of the saddest things about bumper stickers is when the owner is so proud of himself or herself for the cleverness of their bumper stick when it is not even their original thinking. Anyone can read an article, column, or blog and regurgitate the cleverness they read or heard there. Adding real value requires effort, creative thinking, and adding person contributions.

Software development is no different. Effective use of best practices includes learning from one's own experiences so that one can better understand why a best practice is generally good and how it addresses particular problems. Also, best practices should be continually tweaked and should evolve based on community contributions and discussion. Best practices will become even better practices through the combined effort and experiences of the software development community.


How Do We Prevent 'Best Practices' from Becoming 'Bumper Sticker Practices'?

I think we as developers can take certain precautions to prevent "best practices" from becoming "bumper sticker practices." These precautions can be categorized as understanding best practices and applying them judiciously. We are more likely to turn a best practice into a bumper sticker practice when we don't understand a best practice or apply them indiscriminately. Here are some things I try to keep in mind when considering application of a particular best practice.

Understand 'Best Practices' Concept - To me a best practice is a practice that is widely recognized by experienced developers as a practice that generally is superior to alternative practices.

Understand the 'Why' of a Best Practice - A best practice is most effectively applied when the developer understands the necessity for the best practice (improved maintainability or some other desirable feature).

Understand the 'How' of a Best Practice - Understanding how the best practice addresses the particular problem is key to understanding when it truly is a good practice and when it is an irrelevant or bad practice.

Understand Best Circumstances and Worst Circumstances for Best Practice - Although a "best practice" should, in my opinion, be the preferable practice for a majority of situations, there are few, if any, practices that are always the most appropriate in all circumstances. Effective application of a particular best practice requires understanding which situations the best practice is less desirable than alternative practices or even downright detrimental.

Keep in Mind the Value of Others' Experiences and Opinions - One of the most galling aspects of some political bumper stickers is the implication that the owner of the sticker is smarter than people who don't agree with him or her. Not all political bumper stickers are designed to imply that, but many are. Even when I believe strongly in a particular best practice, I try to be open-minded enough to consider if an alternative approach works better in a given situation. There is no reason to be too stubborn about a particular practice if other practices are better.

Continual Learning and Hands-On Experience - Continual exposure to new ideas, concepts, patterns, and languages can be useful in reaffirming understanding of current best practices and in identifying new development best practices.

Know When to Say No - Although I believe that a best practice is one which has earned agreement among experienced developers about being a superior practice in general cases, software development is full of trade-offs and widely varying situations. Our favorite best practice can remain such if we don't misuse or abuse it and end up having a bad experience because of it. Sometimes we just have to let go.

Focus on What Counts - The value to appropriately used best practices is that they can allow large groups of developers with varying skill levels to write reasonable applications meeting many different architectural and design requirements. However, we cannot become so distracted by our best of intentions to apply a best practice that we miss the finer points of a particular problem.

Best Practices Can Be Contradictory - As evidence that software development is full of trade-offs, there are times when two best practices contradict each other. This tends to occur when one "best practice" is best in terms of a certain quality while the other "best practice" is best in terms of a different (and possibly opposite) quality. For example, a "best practice" for maintainable code can sometimes contradict a "best practice" for performance concerns. With software development being so full of trade-offs that even best practices can be contradictory, it is not surprising that we cannot blindly, naively, and uniformly apply the same practice to all circumstances.


Conclusion

I am a strong believer in effectively applied best practices. I believe the collection of best practices can provide significant benefits to the software development community when discussed, debated, applied, and reapplied. New concepts can be woven into past experience to constantly adapt and improve upon our collections of best practices. Best practices are most effectively applied when the developer understands the problem the practice addresses, understands why the practice is superior to alternatives for that particular problem, and understands that no one practice can be "best" all the time in all situations. When best practices are applied without understanding these things, they can quickly turn to "bumper sticker practices" with all the worst characteristics that can be associated with bumper stickers.




Addendum: My True Feelings about Bumper Stickers

I started this post with the relatively strongly worded statement, "I loathe bumper stickers." To be fair, I loathe political bumper stickers and have only a mild dislike of most other bumper stickers. I also must admit to laughing out loud at some particularly clever bumper stickers that did not seem to have any of the most negative characteristics described above (unnecessary flaunting of one's accomplishments/pride, aggressive forcing of opinions on others, trivializing significant and complex issues, etc.). These bumper stickers (like "My kid beat up your honor student" and "My other car is a piece of crap too") are funny. I'd never put them on my vehicle, but they are funny nonetheless.

Likewise, there are good "bumper stickers" in software development. I like the short bumper sticker-like quotations in Jon Louis Bentley's Bumper-Sticker Computer Science. I also like Joshua Bloch's Bumper-Sticker API Design, but note that he goes past my biggest problem with bumper stickers (naive, simple, and pithy statements) to actually describe each point. Both Bentley and Bloch can also get away with a little "bumper sticker" cleverness because there is no question that they speak from experience and knowledge in the computer science arena. They have contributed to the literature and discussions consistently and prominently. In other words, I know there is substance and depth behind their statements.