Saturday, April 25, 2009

The Truth is Out There: Is It At JavaOne and Oracle OpenWorld?

There is no shortage of articles covering the news of Oracle's intent to buy Sun and Sun's agreement to be purchased by Oracle. This level of coverage is justifiable given the potential magnitude of this on development using Java and on many other areas of the information systems and computer science fields. Many of us were not surprised, but now that it has actually happened, there are many questions. The answers to some of these questions may be full of surprises.

It seems that 2009 JavaOne (June 2-5, 2009) and Oracle OpenWorld 2009 (October 11-15, 2009) will likely provide answers to many of our questions and perhaps even prompt a few new questions and even start or strengthen some conspiracy theories. [By the way, I'm especially looking forward to the hallway chat and Q&A session at Colorado Software Summit 2009 (October 25-30, 2009) regarding the latest developments.]

A very recent Java.net poll asked the question, "Which of the technologies highlighted at JavaOne 2009 is of greatest importance for the future of Java?" It is interesting to note that as of this writing (and with this poll question no longer featured on Java.net as the current poll question), there have been only 310 votes so far. I am probably reading more into the responses than I should and the relatively low number of votes could simply imply that the poll question was not significantly interesting or controversial to a large number of developers. Having said that, I wonder if at least part of the low response is due to developers more interested in the overall future of Java than of any one particular aspect of it.

My guess (and that's all it is) is that JavaFX will not reign as the main attraction for a third year running, but that talk of the effects and impact of Oracle buying Sun will dominate JavaOne regardless of the organized presentations and activities. Similarly, but to a lesser degree, the same Oracle/Sun transaction will be a major topic at Oracle OpenWorld. Because Oracle OpenWorld includes many presentations, activities, and attendees with no or very little direct interest in Java, there may be more "other things" to talk about.

Some of the questions that people will be talking about and looking for answers to at these two major conferences are:

* Is 2009 JavaOne the last JavaOne? With Oracle's OpenWorld being a huge event in its own right, will Oracle have interest in maintaining a separate and very large conference? What will JavaOne be like in the future under Oracle if the conference continues?

* Will Oracle support JavaFX with the same passion and resources that Sun did?

* Will Oracle support GlassFish and NetBeans with the same passion and resources that Sun did?

* Will Oracle support MySQL with the same passion and resources that Sun did or is this another conspiracy theory with potential?

* Will Oracle support JRuby and other largely Sun-sponsored community projects with the same passion and resources that Sun did?

* What effect will this have on the Java Community Process (JCP)?

* How will the life of the Java developer change?


Two television series that I have enjoyed remind me of how many of us feel now as we contemplate Oracle's purchase of Sun. Both The X Files (1993-2002) and Lost (2004-present) had/have a way of answering one or two questions now and then while at the same time opening up several times that number of new questions. Although this was/is extremely frustrating at times, I kept/keep watching in a desperate hope to get some answers. In fact, based on my own behavior and the popularity of these series, it seems that we may even like the questions and the speculations that ensue. It will be interesting to see if 2009 JavaOne and Oracle OpenWorld 2009 actually satisfy most of our questions or if, like The X Files and Lost, they answer a few questions while opening up many more. Perhaps we enjoy this ability to speculate in Java-dom as much as we do about our favorite television shows.

Finally, if Oracle is thinking about combining "JavaOne" with "Oracle OpenWorld", a natural blend would be "Oracle JavaWorld", but the "JavaWorld" trademark is already taken. So, if the conferences are combined in the future, what will the new conference's name be?

Effective Java NullPointerException Handling

It doesn't take much Java development experience to learn firsthand what the NullPointerException is about. In fact, one person has highlighted dealing with this as the number one mistake Java developers make. I blogged previously on use of String.value(Object) to reduce unwanted NullPointerExceptions. There are several other simple techniques one can use to reduce or eliminate the occurrences of this common type of RuntimeException that has been with us since JDK 1.0. This blog post collects and summarizes some of the most popular of these techniques.

Check Each Object For Null Before Using

The most sure way to avoid a NullPointerException is to check all object references to ensure that they are not null before accessing one of the object's fields or methods. As the following example indicates, this is a very simple technique.


final String causeStr = "adding String to Deque that is set to null.";
final String elementStr = "Fudd";
Deque<String> deque = null;

try
{
deque.push(elementStr);
log("Successful at " + causeStr, System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
if (deque == null)
{
deque = new LinkedList<String>();
}
deque.push(elementStr);
log( "Successful at " + causeStr
+ " (by checking first for null and instantiating Deque implementation)",
System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}


In the code above, the Deque used is intentionally initialized to null to facilitate the example. The code in the first try block does not check for null before trying to access a Deque method. The code in the second try block does check for null and instantiates an implementation of the Deque (LinkedList) if it is null. The output from both examples looks like this:


ERROR: NullPointerException encountered while trying to adding String to Deque that is set to null.
java.lang.NullPointerException
INFO: Successful at adding String to Deque that is set to null. (by checking first for null and instantiating Deque implementation)


The message following ERROR in the output above indicates that a NullPointerException is thrown when a method call is attempted on the null Deque. The message following INFO in the output above indicates that by checking Deque for null first and then instantiating a new implementation for it when it is null, the exception was avoided altogether.

This approach is often used and, as shown above, can be very useful in avoiding unwanted (unexpected) NullPointerException instances. However, it is not without its costs. Checking for null before using every object can bloat the code, can be tedious to write, and opens more room for problems with development and maintenance of the additional code. For this reason, there has been talk of introducing Java language support for built-in null detection, automatic adding of these checks for null after the initial coding, null-safe types, use of Aspect-Oriented Programming (AOP) to add null checking to byte code, and other null-detection tools.

Groovy already provides a convenient mechanism for dealing with object references that are potentially null. Groovy's safe navigation operator (?.) returns null rather than throwing a NullPointerException when a null object reference is accessed.

Because checking null for every object reference can be tedious and does bloat the code, many developers choose to judiciously select which objects to check for null. This typically leads to checking of null on all objects of potentially unknown origins. The idea here is that objects can be checked at exposed interfaces and then be assumed to be safe after the initial check.

This is a situation where the ternary operator can be particularly useful. Instead of


// retrieved a BigDecimal called someObject
String returnString;
if (someObject != null)
{
returnString = someObject.toEngineeringString();
}
else
{
returnString = "";
}


the ternary operator supports this more concise syntax


// retrieved a BigDecimal called someObject
final String returnString = (someObject != null)
? someObject.toEngineeringString()
: "";
}



Check Method Arguments for Null

The technique just discussed can be used on all objects. As stated in that technique's description, many developers choose to only check objects for null when they come from "untrusted" sources. This often means testing for null first thing in methods exposed to external callers. For example, in a particular class, the developer might choose to check for null on all objects passed to public methods, but not check for null in private methods.

The following code demonstrates this checking for null on method entry. It includes a single method as the demonstrative method that turns around and calls two methods, passing each method a single null argument. One of the methods receiving a null argument checks that argument for null first, but the other just assumes the passed-in parameter is not null.


/**
* Append predefined text String to the provided StringBuilder.
*
* @param builder The StringBuilder that will have text appended to it; should
* be non-null.
* @throws IllegalArgumentException Thrown if the provided StringBuilder is
* null.
*/
private void appendPredefinedTextToProvidedBuilderCheckForNull(
final StringBuilder builder)
{
if (builder == null)
{
throw new IllegalArgumentException(
"The provided StringBuilder was null; non-null value must be provided.");
}
builder.append("Thanks for supplying a StringBuilder.");
}

/**
* Append predefined text String to the provided StringBuilder.
*
* @param builder The StringBuilder that will have text appended to it; should
* be non-null.
*/
private void appendPredefinedTextToProvidedBuilderNoCheckForNull(
final StringBuilder builder)
{
builder.append("Thanks for supplying a StringBuilder.");
}

/**
* Demonstrate effect of checking parameters for null before trying to use
* passed-in parameters that are potentially null.
*/
public void demonstrateCheckingArgumentsForNull()
{
final String causeStr = "provide null to method as argument.";
logHeader("DEMONSTRATING CHECKING METHOD PARAMETERS FOR NULL", System.out);

try
{
appendPredefinedTextToProvidedBuilderNoCheckForNull(null);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
appendPredefinedTextToProvidedBuilderCheckForNull(null);
}
catch (IllegalArgumentException illegalArgument)
{
log(causeStr, illegalArgument, System.out);
}
}


When the above code is executed, the output appears as shown next.


ERROR: NullPointerException encountered while trying to provide null to method as argument.
java.lang.NullPointerException
ERROR: IllegalArgumentException encountered while trying to provide null to method as argument.
java.lang.IllegalArgumentException: The provided StringBuilder was null; non-null value must be provided.


In both cases, an error message was logged. However, the case in which a null was checked for threw an advertised IllegalArgumentException that included additional context information about when the null was encountered. Alternatively, this null parameter could have been handled in a variety of ways. For the case in which a null parameter was not handled, there were no options for how to handle it. Many people prefer to throw a NullPolinterException with the additional context information when a null is explicitly discovered (see Item #60 in the Second Edition of Effective Java or Item #42 in First Edition), but I have a slight preference for IllegalArgumentException when it is explicitly a method argument that is null because I think the very exception adds context details and it is easy to include "null" in the subject.

The technique of checking method arguments for null is really a subset of the more general technique of checking all objects for null. However, as outlined above, arguments to publicly exposed methods are often the least trusted in an application and so checking them may be more important than checking the average object for null.

Checking method parameters for null is also a subset of the more general practice of checking method parameters for general validity as discussed in Item #38 of the Second Edition of Effective Java (Item 23 in First Edition).


Consider Primitives Rather than Objects

I don't think it is a good idea to select a primitive data type (such as int) over its corresponding object reference type (such as Integer) simply to avoid the possibility of a NullPointerException, but there is no denying that one of the advantages of primitive types is that they do not lead to NullPointerExceptions. However, primitives still must be checked for validity (a month cannot be a negative integer) and so this benefit may be small. On the other hand, primitives cannot be used in Java Collections and there are times one wants the ability to set a value to null.

The most important thing is to be very cautious about the combination of primitives, reference types, and autoboxing. There is a warning in Effective Java (Second Edition, Item #49) regarding the dangers, including throwing of NullPointerException, related to careless mixing of primitive and reference types.


Carefully Consider Chained Method Calls

A NullPointerException can be very easy to find because a line number will state where it occurred. For example, a stack trace might look like that shown next:


java.lang.NullPointerException
at dustin.examples.AvoidingNullPointerExamples.demonstrateNullPointerExceptionStackTrace(AvoidingNullPointerExamples.java:222)
at dustin.examples.AvoidingNullPointerExamples.main(AvoidingNullPointerExamples.java:247)


The stack trace makes it obvious that the NullPointerException was thrown as a result of code executed on line 222 of AvoidingNullPointerExamples.java. Even with the line number provided, it can still be difficult to narrow down which object is null if there are multiple objects with methods or fields accessed on the same line.

For example, a statement like someObject.getObjectA().getObjectB().getObjectC().toString(); has four possible calls that might have thrown the NullPointerException attributed to the same line of code. Using a debugger can help with this, but there may be situations when it is preferable to simply break the above code up so that each call is performed on a separate line. This allows the line number contained in a stack trace to easily indicate which exact call was the problem. Furthermore, it facilitates explicit checking each object for null. However, on the downside, breaking up the code increases the line of code count (to some that's a positive!) and may not always be desirable, especially if one is certain none of the methods in question will ever be null.


Make NullPointerExceptions More Informative

In the above recommendation, the warning was to consider carefully use of method call chaining primarily because it made having the line number in the stack trace for a NullPointerException less helpful than it otherwise might be. However, the line number is only shown in a stack trace when the code was compiled with the debug flag turned on. If it was compiled without debug, the stack trace looks like that shown next:


java.lang.NullPointerException
at dustin.examples.AvoidingNullPointerExamples.demonstrateNullPointerExceptionStackTrace(Unknown Source)
at dustin.examples.AvoidingNullPointerExamples.main(Unknown Source)


As the above output demonstrates, there is a method name, but not no line number for the NullPointerException. This makes it more difficult to immediately identify what in the code led to the exception. One way to address this is to provide context information in any thrown NullPointerException. This idea was demonstrated earlier when a NullPointerException was caught and re-thrown with additional context information as a IllegalArgumentException. However, even if the exception is simply re-thrown as another NullPointerException with context information, it is still helpful. The context information helps the person debugging the code to more quickly identify the true cause of the problem.

The following example demonstrates this principle.


final Calendar nullCalendar = null;

try
{
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}

try
{
if (nullCalendar == null)
{
throw new NullPointerException("Could not extract Date from provided Calendar");
}
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}


The output from running the above code looks as follows.


ERROR: NullPointerException encountered while trying to NullPointerException with useful data
java.lang.NullPointerException
ERROR: NullPointerException encountered while trying to NullPointerException with useful data
java.lang.NullPointerException: Could not extract Date from provided Calendar


The first error does not provide any context information and only conveys that it is a NullPointerException. The second error, however, had explicit context information added to it which would go a long way in helping identify the source of the exception.


Use String.valueOf Rather than toString

As described previously, one of the surest methods for avoiding NullPointerException is to check the object being referenced for null first. The String.valueOf(Object) method is a good example of a case where this check for null can be done implicitly without any additional effort on the developer's part. I blogged on this previously, but include a brief example of its use here.


final String cause = "getting BigDecimal as String representation";
final BigDecimal decimal = null;
try
{
final String decimalStr = decimal.toString();
log("Retrieved " + decimalStr + " by " + cause, System.out);
}
catch (NullPointerException nullPointer)
{
log(cause, nullPointer, System.out);
}

try
{
final String decimalStr = String.valueOf(decimal);
log("Retrieved " + decimalStr + " by " + cause, System.out);
}
catch (NullPointerException nullPointer)
{
log(cause, nullPointer, System.out);
}


The output from this code sample appears as follows.


ERROR: NullPointerException encountered while trying to getting BigDecimal as String representation
java.lang.NullPointerException
INFO: Retrieved null by getting BigDecimal as String representation


This example demonstrates that use of String.valueOf(Object) enables the attempt to get the null BigDecimal's String representation be provided with a "null" string rather than a NullPointerException being thrown. This can be a particularly useful technique for implementing objects' toString() implementations.

One minor downside of use of String.valueOf stems from its behavior that is normally a positive. Although there are many cases where having a null object's String representation be returned as a "null" String is better than having a NullPointerException thrown, this can sometimes be a disadvantage if used indiscriminately. For example, String methods called on the String returned by valueOf(Object) will return a real String with the characters null. This is proven by the following code.


final String nullString = null;
final String nullStringValueOf = String.valueOf(nullString);
log("The length of the nullString is " + nullStringValueOf.length(),
System.out);
if (nullStringValueOf.isEmpty())
{
log("Empty String!", System.out);
}
else
{
log("String is NOT empty.", System.out);
}


The code above leads to these results that prove that there is a String "null" returned by String.valueOf(Object) when it is called upon an object with a null reference.


INFO: The length of the nullString is 4
INFO: String is NOT empty.


As the code and results above show, use String.valueOf(Object) on a null object will actually return a non-empty String (four characters n-u-l-l).


Avoid Returning Nulls

In Item #43 of the Second Edition of Effective Java (Item #27 in the First Edition), Joshua Bloch recommends returning empty arrays or empty collections rather than returning null. He points out that returning null requires client code to make special effort to handle such a contingency. When a client fails to do so, a NullPointerException is almost certainly going to be encountered down the road. The Java Collections class has useful methods for returning empty Collections that make it really easy to follow this advice. I have often found it to be similarly useful to return empty Strings rather than null for methods returning a String to indicate no match or error condition.

While there are problems associated with returning a null to indicate a failure or less than successful status, returning a null to indicate success is even more troubling because it is not normally associated with a positive outcome. In other words, it is typically not a good idea to return null as an indicator of success and a non-null object as an indicator of some type of failure.

The null object pattern is a well-known and slightly sophisticated approach to returning an object to the caller that indicates a null condition. It is more work than returning null, but is safer for the client.


Discourage Passing of Null Parameters

I previously mentioned the importance of checking passed-in parameters for null. There are several steps one can take to reduce the chance of nulls being passed into constructors or methods in the first place. One easy approach is to specify in the Javadoc comments on the method or constructor which arguments must not be null. This is appropriately documented in the @param tags. Similarly, if an exception is thrown when a null parameter is encountered, that exception can be advertised in the Javadoc comment with the @throws tag.

A common situation in which null gets passed as a parameter too often is in constructors accepting large lists of parameters. In Item #2 of the Second Edition of Effective Java, Bloch recommends employing the builder pattern instead of the telescoping constructor pattern. The appeal of this approach is that clients only need specify required parameters in the constructor and optional parameters only need be specified if applicable. This reduces the need for clients to pass null and that will hopefully reduce the likelihood of passing null seeming like a normal thing to do. The chapter that includes this item from Effective Java is available here. This idea is also covered in A Java Builder Pattern, Effective Java Reloaded: This Time It's For Real, and the Java Specialists' Book Review.


Calls String.equals(String) on 'Safe' Non-Null String

Some Java Strings are more likely to be non-null than others. For example, literal Strings are obviously not null. String constants and other Strings with well-known sources are also more trusted to be non-null. When comparing two Strings for equality with the equals method (or the equalsIgnoreCase method), it is typically best to call the equals method on the String that is more likely to NOT be null. This reduces the chances of a NullPointerException.

The following example code compares the two approaches, trying to access equals on a String that is really null and on a non-null String. The results are very different.


final String safeStringOrConstant = "Sally Ann Cavanaugh";
final String nullString = null;

try
{
if (nullString.equals(safeStringOrConstant))
{
log(nullString + " IS equal to " + safeStringOrConstant, System.out);
}
else
{
log(nullString + " is NOT equal to " + safeStringOrConstant, System.out);
}
}
catch (NullPointerException nullPointer)
{
log("call 'equals' on null String", nullPointer, System.out);
}

try
{
if (safeStringOrConstant.equals(nullString))
{
log(nullString + " IS equal to " + safeStringOrConstant, System.out);
}
else
{
log(nullString + " is NOT equal to " + safeStringOrConstant, System.out);
}
}
catch (NullPointerException nullPointer)
{
log("call 'equals' on non-null String", nullPointer, System.out);
}


The results of running the code above are shown next.


ERROR: NullPointerException encountered while trying to call 'equals' on null String
java.lang.NullPointerException
INFO: null is NOT equal to Sally Ann Cavanaugh


When the equals method was invoked on a null, the only text message we were presented with was the name of the exception. By invoking the equals method against a safe, non-null String, we avoid the exception altogether and got a correct result (the null passed to the equals method does not match the String on which the equals method is invoked).


Let Others Do the Heavy Lifting

As mentioned before, one of the safest ways to avoid the NullPointerException is to add code to check each object for null before accessing its methods and attributes. It is really nice when this check can be done without any extra effort. The String.valueOf(Object) method covered earlier does this for calling toString() on potentially null references. There are other libraries that provide similar built-in null-checking support so that you don't need to explicitly check for null. An example is ToStringBuilder, which builds toString() representations of objects and gracefully handles any null references in the object.


The Complete Sample Code Listing


package dustin.examples;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.Deque;
import java.util.LinkedList;

/**
* Examples demonstrating avoidance, minimization, or more effective use of
* NullPointerExceptions in Java.
*/
public class AvoidingNullPointerExamples
{
private static final String NEW_LINE = System.getProperty("line.separator");

/**
* Demonstrate how the order of a String equality comparison can reduce or
* eliminate NullPointerExceptions.
*/
public void demonstrateOrderOfStringEqualityCheck()
{
logHeader("ORDER IN STRING COMPARISON", System.out);
final String safeStringOrConstant = "Sally Ann Cavanaugh";
final String nullString = null;

try
{
if (nullString.equals(safeStringOrConstant))
{
log(nullString + " IS equal to " + safeStringOrConstant, System.out);
}
else
{
log(nullString + " is NOT equal to " + safeStringOrConstant, System.out);
}
}
catch (NullPointerException nullPointer)
{
log("call 'equals' on null String", nullPointer, System.out);
}

try
{
if (safeStringOrConstant.equals(nullString))
{
log(nullString + " IS equal to " + safeStringOrConstant, System.out);
}
else
{
log(nullString + " is NOT equal to " + safeStringOrConstant, System.out);
}
}
catch (NullPointerException nullPointer)
{
log("call 'equals' on non-null String", nullPointer, System.out);
}
}

/**
* Demonstrate how supplying context information to an
* {@link NullPointerException} can make it more useful for clients and for
* debugging.
*/
public void demonstrateThrowingMoreUsefulNullPointerException()
{
logHeader("CONSTRUCT NULLPOINTEREXCEPTION WITH USEFUL DATA", System.out);
final Calendar nullCalendar = null;

try
{
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}

try
{
if (nullCalendar == null)
{
throw new NullPointerException("Could not extract Date from provided Calendar");
}
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}
}

/**
* Append predefined text {@link String} to the provided {@link StringBuilder}.
*
* @param builder The StringBuilder that will have text appended to it; should
* be non-null.
* @throws IllegalArgumentException Thrown if the provided StringBuilder is
* null.
*/
private void appendPredefinedTextToProvidedBuilderCheckForNull(
final StringBuilder builder)
{
if (builder == null)
{
throw new IllegalArgumentException(
"The provided StringBuilder was null; non-null value must be provided.");
}
builder.append("Thanks for supplying a StringBuilder.");
}

/**
* Append predefined text {@link String} to the provided {@link StringBuilder}.
*
* @param builder The StringBuilder that will have text appended to it; should
* be non-null.
*/
private void appendPredefinedTextToProvidedBuilderNoCheckForNull(
final StringBuilder builder)
{
builder.append("Thanks for supplying a StringBuilder.");
}

/**
* Demonstrate effect of checking parameters for null before trying to use
* passed-in parameters that are potentially null.
*/
public void demonstrateCheckingArgumentsForNull()
{
final String causeStr = "provide null to method as argument.";
logHeader("DEMONSTRATING CHECKING METHOD PARAMETERS FOR NULL", System.out);

try
{
appendPredefinedTextToProvidedBuilderNoCheckForNull(null);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
appendPredefinedTextToProvidedBuilderCheckForNull(null);
}
catch (IllegalArgumentException illegalArgument)
{
log(causeStr, illegalArgument, System.out);
}
}

/**
* Demonstrate checking for null before trying to access an object's data
* methods or attributes.
*/
public void demonstrateCheckingForNullFirst()
{
logHeader("DEMONSTRATE CHECKING FOR NULL BEFORE ACTING", System.out);
final String causeStr = "adding String to Deque that is set to null.";
final String elementStr = "Fudd";
Deque<String> deque = null;

try
{
deque.push(elementStr);
log("Successful at " + causeStr, System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
if (deque == null)
{
deque = new LinkedList<String>();
}
deque.push(elementStr);
log(
"Successful at " + causeStr
+ " (by checking first for null and instantiating Deque implementation)",
System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}
}

/**
* Demonstrate how use of {@code String.valueOf(Object)} provides functionality
* similar to calling {@code toString()} on an object without the risk of a
* {@code NullPointerException}.
*/
public void demonstrateUsingStringValueOf()
{
logHeader("USING STRING.VALUEOF RATHER THAN TOSTRING", System.out);
final String cause = "getting BigDecimal as String representation";
final BigDecimal decimal = null;
try
{
final String decimalStr = decimal.toString();
log("Retrieved " + decimalStr + " by " + cause, System.out);
}
catch (NullPointerException nullPointer)
{
log(cause, nullPointer, System.out);
}

try
{
final String decimalStr = String.valueOf(decimal);
log("Retrieved " + decimalStr + " by " + cause, System.out);
}
catch (NullPointerException nullPointer)
{
log(cause, nullPointer, System.out);
}
}

/**
* Demonstrates that while String.valueOf(String) does perform like a
* {@code toString()} call without the risk of a {@code NullPointerException},
* it also has the side effects of returning a non-null, non-empty String
* (four characters) for an object that is actually null. This is because
* it returns "null".
*/
public void demonstratingSideEffectsOfStringValueOf()
{
logHeader("SIDE EFFECTS OF STRING.VALUEOF(OBJECT)", System.out);
final String nullString = null;
final String nullStringValueOf = String.valueOf(nullString);
log("The length of the nullString is " + nullStringValueOf.length(),
System.out);
if (nullStringValueOf.isEmpty())
{
log("Empty String!", System.out);
}
else
{
log("String is NOT empty.", System.out);
}
}

/**
* Demonstrate a {@code NullPointerException} stack trace. To see the
* difference between debug and nodebug, compile this class both with debug
* turned on and with debug turned off and run this method with each setting.
* With debug on, line numbers will be included in the stack trace; these line
* numbers will not be included with the nodebug mode
*/
public void demonstrateNullPointerExceptionStackTrace()
{
logHeader("EXAMPLE STACK TRACE FOR NULLPOINTERECEPTION", System.out);
final Object nullObject = null;
try
{
final String objectString = nullObject.toString();
}
catch (NullPointerException nullPointer)
{
final PrintWriter writer = new PrintWriter(System.out);
nullPointer.printStackTrace(writer);
writer.close();
log("END OF NULL POINTER STACK TRACE", System.out);
}
}

/**
* Main executable method for running all of the demonstrations of techniques
* for reducing or eliminating dealing with thrown {@code NullPointerException}s.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
final AvoidingNullPointerExamples demonstrator =
new AvoidingNullPointerExamples();
demonstrator.demonstrateOrderOfStringEqualityCheck();
demonstrator.demonstrateThrowingMoreUsefulNullPointerException();
demonstrator.demonstrateCheckingArgumentsForNull();
demonstrator.demonstrateCheckingForNullFirst();
demonstrator.demonstrateUsingStringValueOf();
demonstrator.demonstratingSideEffectsOfStringValueOf();
demonstrator.demonstrateNullPointerExceptionStackTrace();
}

/**
* Log header information by logging provided message to the provided
* {@link OutputStream}.
*
* @param headerMessage The text portion of the header being logged.
* @param out OutputStream to which complete header is written.
*/
public static void logHeader(final String headerMessage, final OutputStream out)
{
final String headerSeparator =
"====================================================================";
final String loggedString =
NEW_LINE + headerSeparator + NEW_LINE
+ headerMessage + NEW_LINE
+ headerSeparator + NEW_LINE;

try
{
out.write(loggedString.getBytes());
}
catch (IOException ioEx)
{
System.out.print(loggedString);
}
}

/**
* Log provided text message to the provided {@link OutputStream}.
*
* @param messageToLog String to be logged.
* @param out OutputStream to which to write the log.
*/
public static void log(final String messageToLog, final OutputStream out)
{
final String infoStr = "INFO: " + messageToLog;
try
{
out.write((infoStr + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
System.out.println(infoStr);
}
}

/**
* Log {@code NullPointerException} error condition by logging the provided
* action leading to the {@code NullPointerException} along with the
* {@code NullPointerException} itself to the provided OutputStream.
*
* @param actionCausingNullPointerException Action that led to the throwing
* of the NullPointerException.
* @param exception NullPointerException that was caught.
* @param out OutputStream to which to write log information.
*/
public static void log(
final String actionCausingNullPointerException,
final NullPointerException exception,
final OutputStream out)
{
final String errorStr =
"ERROR: NullPointerException encountered while trying to "
+ actionCausingNullPointerException;
try
{
out.write((errorStr + NEW_LINE).getBytes());
out.write((exception.toString() + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
System.err.println(errorStr + exception.toString());
}
}

/**
* Log {@link Exception} information by logging the provided action leading
* to the general {@code Exception} along with the general {@code Exception}
* itself to the provided {@link OutputStream}.
*
* @param actionCausingNullPointerException Action that led to the throwing
* of the rException.
* @param exception Exception that was caught.
* @param out OutputStream to which to write log information.
*/
public static void log(
final String actionCausingNullPointerException,
final Exception exception,
final OutputStream out)
{
final String errorStr =
"ERROR: " + exception.getClass().getSimpleName()
+ " encountered while trying to "
+ actionCausingNullPointerException;
try
{
out.write((errorStr + NEW_LINE).getBytes());
out.write((exception.toString() + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
System.err.println(errorStr + exception.toString());
}
}
}


The complete output when this code is run as shown above is shown next.


====================================================================
ORDER IN STRING COMPARISON
====================================================================
ERROR: NullPointerException encountered while trying to call 'equals' on null String
java.lang.NullPointerException
INFO: null is NOT equal to Sally Ann Cavanaugh

====================================================================
CONSTRUCT NULLPOINTEREXCEPTION WITH USEFUL DATA
====================================================================
ERROR: NullPointerException encountered while trying to NullPointerException with useful data
java.lang.NullPointerException
ERROR: NullPointerException encountered while trying to NullPointerException with useful data
java.lang.NullPointerException: Could not extract Date from provided Calendar

====================================================================
DEMONSTRATING CHECKING METHOD PARAMETERS FOR NULL
====================================================================
ERROR: NullPointerException encountered while trying to provide null to method as argument.
java.lang.NullPointerException
ERROR: IllegalArgumentException encountered while trying to provide null to method as argument.
java.lang.IllegalArgumentException: The provided StringBuilder was null; non-null value must be provided.

====================================================================
DEMONSTRATE CHECKING FOR NULL BEFORE ACTING
====================================================================
ERROR: NullPointerException encountered while trying to adding String to Deque that is set to null.
java.lang.NullPointerException
INFO: Successful at adding String to Deque that is set to null. (by checking first for null and instantiating Deque implementation)

====================================================================
USING STRING.VALUEOF RATHER THAN TOSTRING
====================================================================
ERROR: NullPointerException encountered while trying to getting BigDecimal as String representation
java.lang.NullPointerException
INFO: Retrieved null by getting BigDecimal as String representation

====================================================================
SIDE EFFECTS OF STRING.VALUEOF(OBJECT)
====================================================================
INFO: The length of the nullString is 4
INFO: String is NOT empty.

====================================================================
EXAMPLE STACK TRACE FOR NULLPOINTERECEPTION
====================================================================
java.lang.NullPointerException
at dustin.examples.AvoidingNullPointerExamples.demonstrateNullPointerExceptionStackTrace(AvoidingNullPointerExamples.java:239)
at dustin.examples.AvoidingNullPointerExamples.main(AvoidingNullPointerExamples.java:265)



Conclusion

The NullPointerException can be very helpful in identifying problems in our applications and especially in identifying problems with many assumptions we often make when developing software. However, there are times when we encounter them without any benefit or new information simply because we have not taken proper steps to avoid them. This posting has attempted to cover techniques that are commonly used to reduce NullPointerException exposure, to make valid NullPointerExceptions more meaningful, and to handle NullPointerExceptions more gracefully. Use of these techniques can reduce the number of NullPointerExceptions encountered, increase the quality of those that are encountered, and improve out ability to identify the very problems that that remaining NullPointerExceptions are meant to convey.


Additional References

* How to Avoid '!= null' Statements in Java?

* StackOverflow: What is a NullPointerException?

* NullPointerException

* Java Programming: Preventing NullPointerException

* Basics Uncovered: NullPointerException

* java.lang.NullPointerException

* A Small Tip on String to Avoid NullPointerException

* Null Objects

* Introduce Null Object

* IMHO: Preventing NullPointerException

* Preventing the NullPointerException in Java

* Detecting NullPointerException with Transparent Checks (Added 10 October 2009)

Monday, April 20, 2009

Oracle Buying Sun: Not That Big of a Surprise

Today's announcement regarding Oracle buying Sun is not that big of a surprise given the recent failed deal between IBM and Sun and the precarious position it left Sun in. Although recent events made this not all that surprising, I do have to admit that I would never have believed two years ago that Oracle would be acquiring BEA and Sun in 2008 and 2009 respectively. With Oracle's acquisition of BEA, it seemed that the Big Three of the Java world were Sun, IBM, and Oracle.

Of course, Sun is much more than just Java, even if many of us who work with Java on daily basis forget this sometimes. I am sure that Oracle was attracted to several other things about Sun as well. However, Oracle's commitment to Java is obvious with their numerous Java-related offerings on Oracle Technology Network, their many Java-oriented products and services, and especially with their Oracle Fusion middleware line being heavily Java-focused.

Just as I wondered about the future of NetBeans and GlassFish with the rumored purchase of Sun by IBM, the same thoughts apply with Oracle purchasing Sun. In fact, Oracle is already heavily invested in its own JDeveloper and has contributed to Eclipse (including Oracle Enterprise Pack for Eclipse), so NetBeans is a third IDE they will have involvement with at this point. It is difficult for me to believe they will want to commit resources to all three, but that doesn't necessarily mean it won't happen. In addition, Oracle already has more than one of its own application servers in WebLogic and Oracle Application Server (and OC4J Standalone). Again, it is difficult to imagine Oracle wanting to continue investing resources in yet another application server (GlassFish), though Oracle has contributed to GlassFish as an open source project in the past.

If I had been forced to bet money on who would try to get Sun after the IBM/Sun talks fell through, I would have put my money on Oracle. That being said, I guess I must admit a small amount of surprise when it was actually announced.

JavaScript in Java

The recent JavaLobby post The Top 10 Unused Features in Java has been extremely popular. At the time of this writing, it is the top ranked post in the DZone Top Links category. In addition a reply to it has been posted as well. There are many interesting observations about underutilized features in Java in both blogs posts and I agree with some more than others. However, item that really caught my attention was the assertion that Java SE 6 is one of the most unused Java features.

I really enjoy working with Java SE 6 and have written about or blogged on Java SE 6 features several times in the past. In this blog posting, I intend to demonstrate a portion of Java SE 6's ability to host execute JavaScript code.

Most Java developers and JavaScript developers understand that besides the four letters "J-A-V-A," JavaScript and Java have very little in common other than some C-like heritage. Still, it can be useful at times to run a scripting language from within Java code and Java SE 6 allows this.

The javax.script package was introduced with Java SE 6 and includes classes, interfaces, and a checked exception related to use of scripting engines within Java. This blog posting will focus on ScriptEngineFactory, ScriptEngineManager, ScriptEngine, and ScriptException.

One of the first things one might want to do is to determine which scripting engines are already available. The next snippet of code shows how easy this is to do with Java SE 6.


final ScriptEngineManager manager = new ScriptEngineManager();
for (final ScriptEngineFactory scriptEngine : manager.getEngineFactories())
{
System.out.println(
scriptEngine.getEngineName() + " ("
+ scriptEngine.getEngineVersion() + ")" );
System.out.println(
"\tLanguage: " + scriptEngine.getLanguageName() + "("
+ scriptEngine.getLanguageVersion() + ")" );
System.out.println("\tCommon Names/Aliases: ");
for (final String engineAlias : scriptEngine.getNames())
{
System.out.println(engineAlias + " ");
}
}


The code shown above generates output like that shown in the next screen snapshot.



As this image demonstrates, the Mozilla Rhino JavaScript engine is included with Sun's Java SE 6. We also see some "common names" that are associated with this particular engine. Any of these names can be used to lookup this engine. In later examples in this post, I will be using the common name "js" for this lookup.

The next code sample will take advantage of the provided Rhino JavaScript engine to execute some JavaScript code from Java code. In this case, we'll be taking advantage of JavaScript's toExponential function.


/**
* Write number in exponential form.
*
* @param numberToWriteInExponentialForm The number to be represented in
* exponential form.
* @param numberDecimalPlaces The number of decimal places to be used in the
* exponential representation.
*/
public static void writeNumberAsExponential(
final Number numberToWriteInExponentialForm,
final int numberDecimalPlaces)
{
final ScriptEngine engine = manager.getEngineByName("js");
try
{
engine.put("inputNumber", numberToWriteInExponentialForm);
engine.put("decimalPlaces", numberDecimalPlaces);
engine.eval("var outputNumber = inputNumber.toExponential(decimalPlaces);");
final String exponentialNumber = (String) engine.get("outputNumber");
System.out.println("Number: " + exponentialNumber);
}
catch (ScriptException scriptException)
{
LOGGER.severe(
"ScriptException encountered trying to write exponential: "
+ scriptException.toString());
}
}


The code above directly invokes JavaScript using the ScriptEngine.eval(String) method to evaluate the provided String containing JavaScript syntax. Before invocation of the eval method, two parameters are "passed in" (bound) to the JavaScript code via ScriptEngine.put(String,Object) calls. The result object of the executed JavaScript is accessed in the Java code using a ScriptEngine.get(String) call.

To demonstrate the above code using the toExponential function, I'll use the following "client" code.


final int sourceNumber = 675456;
writeNumberAsExponential(sourceNumber, 1, System.out);
writeNumberAsExponential(sourceNumber, 2, System.out);
writeNumberAsExponential(sourceNumber, 3, System.out);
writeNumberAsExponential(sourceNumber, 4, System.out);
writeNumberAsExponential(sourceNumber, 5, System.out);


When the above code is run against the writeNumberAsExponential method shown earlier and JavaScript is employed, the output appears similar to that shown in the next screen snapshot.



This example is enough to demonstrate how easy it is to invoke JavaScript functionality from within Java SE 6. However, this could be implemented even more generically as the next two examples will demonstrate. The first example shows invocation of relatively arbitrary JavaScript with no parameters passed/bound and the second example demonstrates invocation of relatively arbitrary JavaScript with parameters passed/bound.

A relatively arbitrary JavaScript string can be processed with code similar to that shown next.


/**
* Process the passed-in JavaScript script that should include an assignment
* to a variable with the name prescribed by the provided nameOfOutput and
* may include parameters prescribed by inputParameters.
*
* @param javaScriptCodeToProcess The String containing JavaScript code to
* be evaluated. This String is not checked for any type of validity and
* might possibly lead to the throwing of a ScriptException, which would
* be logged.
* @param nameOfOutput The name of the output variable associated with the
* provided JavaScript script.
* @param inputParameters Optional map of parameter names to parameter values
* that might be employed in the provided JavaScript script. This map
* may be null if no input parameters are expected in the script.
*/
public static Object processArbitraryJavaScript(
final String javaScriptCodeToProcess,
final String nameOfOutput,
final Map<String, Object> inputParameters)
{
Object result = null;
final ScriptEngine engine = manager.getEngineByName("js");
try
{
if (inputParameters != null)
{
for (final Map.Entry<String,Object> parameter :
inputParameters.entrySet())
{
engine.put(parameter.getKey(), parameter.getValue());
}
}
engine.eval(javaScriptCodeToProcess);
result = engine.get(nameOfOutput);
}
catch (ScriptException scriptException)
{
LOGGER.severe(
"ScriptException encountered trying to write arbitrary JavaScript '"
+ javaScriptCodeToProcess + "': "
+ scriptException.toString());
}
return result;
}


The code above provides quite a bit of flexibility in terms of the JavaScript that can be processed. This is probably not the best idea for production code, but does make it easier to demonstrate use of various JavaScript features within Java.

The first example to use this relatively arbitrary JavaScript processing takes advantage of JavaScript's Date object. The sample code is shown next.


System.out.println(
"Today's Date: "
+ processArbitraryJavaScript(
"var date = new Date(); var month = (date.getMonth()+1).toFixed(0)",
"month",
null) + "/"
+ processArbitraryJavaScript(
"var date = new Date(); var day = date.getDate().toFixed(0)",
"day",
null) + "/"
+ processArbitraryJavaScript(
"var date = new Date(); var year = date.getFullYear().toFixed(0)",
"year",
null) );


This code specifies that a JavaScript Date should be retrieved (which will be the current date) and that month, date of month, and full year should be extracted from that instantiated Date. The output for this appears next.



The last example worked on an arbitrary JavaScript String but did not use any parameters. The next example demonstrates providing of parameters to this arbitrary JavaScript String processing as it demonstrates use of JavaScript's pow function. The code for this example is listed next.


final Map<String, Object> exponentParameters = new HashMap<String, Object>();
exponentParameters.put("base", 2);
exponentParameters.put("exponent", 5);
System.out.println(
"2 to the 5 is: "
+ processArbitraryJavaScript(
"var answer = Math.pow(base,exponent)",
"answer",
exponentParameters) );


The output from running this example is shown in the following screen snapshot.



For my final example of this blog posting, I demonstrate the standard toString() output of the ScriptException declared in some of the previous examples. The ScriptEngine.eval method throws this checked exception if there is an error in executing/evaluating the provided script. This method also throws a NullPointerException if the provided String is null. The code used to force a script error is shown next.


/**
* Intentionally cause script handling error to show the type of information
* that a ScriptException includes.
*/
public static void testScriptExceptionHandling()
{
System.out.println(processArbitraryJavaScript("Garbage In", "none", null));
}


This code provides a nonsensical script (in terms of JavaScript syntax), but that is exactly what is needed to demonstrate the ScriptException.toString(), which is called as part of the exception handling in the method shown above for handling an arbitrary JavaScript String. When the code is executed, we see the exception information as shown in the next image.



The portion of the output that comes from ScriptException.toString() is the portion that states: "javax.script.ScriptException: sun.org.mozilla.javascript.internal.EvaluatorException: missing ; before statement (<Unknown source>#1) in <Unknown source> at line number 1."

The ScriptException contains the file name, line number, and column number of the exception, which is especially helpful if a file with JavaScript code is provided for evaluation.


Conclusion

Java SE 6 makes it simple to use JavaScript within Java code. Other scripting engines can also be associated with Java, but it is handy to have one provided out-of-the-box with Mozilla Rhino.


Complete Code and Output Screen Snapshot

For completeness, I am including the complete code listing in one place here and the resultant output after that.

JavaScriptInJavaExample.java


package dustin.examples;

import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/**
* This example demonstrates using JavaScript within Java SE 6.
*/
public class JavaScriptInJavaExample
{
private final static ScriptEngineManager manager = new ScriptEngineManager();

/** Using java.util.logging. */
private final static Logger LOGGER = Logger.getLogger(
JavaScriptInJavaExample.class.getName());

private final static String NEW_LINE = System.getProperty("line.separator");

private final static String HEADER_SEPARATOR =
"=======================================================================";

/**
* Write the key information about the provided Script Engine Factories to
* the provided OutputStream.
*
* @param scriptEngineFactories Script Engine Factories for which key data
* should be written to the OutputStream.
* @param out OutputStream to which to write Script Engine Factory details.
*/
public static void writeScriptEngineFactoriesToOutputStream(
final List<ScriptEngineFactory> scriptEngineFactories,
final OutputStream out)
{
printHeader("Available Script Engines", out);
try
{
out.write(NEW_LINE.getBytes());
for (final ScriptEngineFactory scriptEngine : scriptEngineFactories)
{
out.write(
( scriptEngine.getEngineName() + " ("
+ scriptEngine.getEngineVersion() + ")" + NEW_LINE).getBytes());
out.write(
( "\tLanguage: " + scriptEngine.getLanguageName() + "("
+ scriptEngine.getLanguageVersion() + ")" + NEW_LINE).getBytes());
out.write("\tCommon Names/Aliases: ".getBytes());
for (final String engineAlias : scriptEngine.getNames())
{
out.write((engineAlias + " ").getBytes());
}
out.write(NEW_LINE.getBytes());
}
out.write(NEW_LINE.getBytes());
}
catch (IOException ioEx)
{
LOGGER.severe(
"Could not write to provided OutputStream: "
+ ioEx.toString());
}
}

/**
* Show availability of scripting engines supported in this environment.
*/
public static void testSupportedScriptingEngines()
{
writeScriptEngineFactoriesToOutputStream(
manager.getEngineFactories(), System.out);
}

/**
* Write number in exponential form.
*
* @param numberToWriteInExponentialForm The number to be represented in
* exponential form.
* @param numberDecimalPlaces The number of decimal places to be used in the
* exponential representation.
* @param out OutputStream to which exponential number should be written.
*/
public static void writeNumberAsExponential(
final Number numberToWriteInExponentialForm,
final int numberDecimalPlaces,
final OutputStream out)
{
final ScriptEngine engine = manager.getEngineByName("js");
try
{
engine.put("inputNumber", numberToWriteInExponentialForm);
engine.put("decimalPlaces", numberDecimalPlaces);
engine.eval("var outputNumber = inputNumber.toExponential(decimalPlaces);");
final String exponentialNumber = (String) engine.get("outputNumber");
out.write(("Number: " + exponentialNumber + NEW_LINE).getBytes());
}
catch (ScriptException scriptException)
{
LOGGER.severe(
"ScriptException encountered trying to write exponential: "
+ scriptException.toString());
}
catch (IOException ioEx)
{
LOGGER.severe(
"IOException encountered trying to write exponential: "
+ ioEx.toString());
}
}

/**
* Test JavaScript within Java.
*/
public static void testJavaScriptInJava()
{
printHeader("Writing Numbers as Exponentials", System.out);
final int sourceNumber = 675456;
writeNumberAsExponential(sourceNumber, 1, System.out);
writeNumberAsExponential(sourceNumber, 2, System.out);
writeNumberAsExponential(sourceNumber, 3, System.out);
writeNumberAsExponential(sourceNumber, 4, System.out);
writeNumberAsExponential(sourceNumber, 5, System.out);
}

/**
* Process the passed-in JavaScript script that should include an assignment
* to a variable with the name prescribed by the provided nameOfOutput and
* may include parameters prescribed by inputParameters.
*
* @param javaScriptCodeToProcess The String containing JavaScript code to
* be evaluated. This String is not checked for any type of validity and
* might possibly lead to the throwing of a ScriptException, which would
* be logged.
* @param nameOfOutput The name of the output variable associated with the
* provided JavaScript script.
* @param inputParameters Optional map of parameter names to parameter values
* that might be employed in the provided JavaScript script. This map
* may be null if no input parameters are expected in the script.
*/
public static Object processArbitraryJavaScript(
final String javaScriptCodeToProcess,
final String nameOfOutput,
final Map<String, Object> inputParameters)
{
Object result = null;
final ScriptEngine engine = manager.getEngineByName("js");
try
{
if (inputParameters != null)
{
for (final Map.Entry<String,Object> parameter :
inputParameters.entrySet())
{
engine.put(parameter.getKey(), parameter.getValue());
}
}
engine.eval(javaScriptCodeToProcess);
result = engine.get(nameOfOutput);
}
catch (ScriptException scriptException)
{
LOGGER.severe(
"ScriptException encountered trying to write arbitrary JavaScript '"
+ javaScriptCodeToProcess + "': "
+ scriptException.toString());
}
return result;
}

/**
* Write passed-in headerMessage text to provided OutputStream using clear
* header demarcation.
*
* @param headerMessage Text to be written to header.
* @param out OutputStream to which header should be written.
*/
private static void printHeader(
final String headerMessage, final OutputStream out)
{
try
{
out.write((NEW_LINE + HEADER_SEPARATOR + NEW_LINE).getBytes());
out.write((headerMessage + NEW_LINE).getBytes());
out.write((HEADER_SEPARATOR + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
LOGGER.warning(
"Not able to write header with text '"
+ headerMessage
+ " out to provided OutputStream: " + ioEx.toString());
System.out.println(HEADER_SEPARATOR);
System.out.println(headerMessage);
System.out.println(HEADER_SEPARATOR);
}
}

/**
* Demonstrate execution of an arbitrary JavaScript script within Java that
* does NOT include parameters.
*/
public static void testArbitraryJavaScriptStringEvaluationWithoutParameters()
{
printHeader(
"Use JavaScript's Date Object [script with NO parameters]", System.out);
System.out.println(
NEW_LINE + "Today's Date: "
+ processArbitraryJavaScript(
"var date = new Date(); var month = (date.getMonth()+1).toFixed(0)",
"month",
null) + "/"
+ processArbitraryJavaScript(
"var date = new Date(); var day = date.getDate().toFixed(0)",
"day",
null) + "/"
+ processArbitraryJavaScript(
"var date = new Date(); var year = date.getFullYear().toFixed(0)",
"year",
null)
+ NEW_LINE);
}

/**
* Demonstrate execution of an arbritrary JavaScript script within Java
* that includes parameters.
*/
public static void testArbitraryJavaScriptStringEvaluationWithParameters()
{
printHeader(
"Use JavaScript's Math.pow(base,exponent) function [script WITH parameters]",
System.out);
final Map<String, Object> exponentParameters = new HashMap<String, Object>();
exponentParameters.put("base", 2);
exponentParameters.put("exponent", 5);
System.out.println(
"2 to the 5 is: "
+ processArbitraryJavaScript(
"var answer = Math.pow(base,exponent)",
"answer",
exponentParameters)
+ NEW_LINE);
}

/**
* Intentionally cause script handling error to show the type of information
* that a ScriptException includes.
*/
public static void testScriptExceptionHandling()
{
printHeader(
"Intentional Script Error to Demonstate ScriptException", System.out);
System.out.println(
NEW_LINE + processArbitraryJavaScript("Garbage In", "none", null));
}

/**
* Main executable for demonstrating running of script code within Java.
*/
public static void main(final String[] arguments)
{
testSupportedScriptingEngines();
testJavaScriptInJava();
testArbitraryJavaScriptStringEvaluationWithoutParameters();
testArbitraryJavaScriptStringEvaluationWithParameters();
testScriptExceptionHandling();
}
}


Output from Running Above Code Sample

Saturday, April 18, 2009

The Value of String.valueOf

Most Java developers have probably had their fill of NullPointerException. Most of us have learned the value of doing certain things to reduce our "opportunities" of encountering the NullPointerException. Indeed, there is a Wiki page dedicated to preventing or reducing NullPointerExceptions.

Several people have argued for additional language support for improved and easier handling of potential null. These include Java SE 7 proposals, Optimized Null Check, and Kinga Dobolyi's thesis Changing Java’s Semantics for Handling Null Pointer Exceptions.

Among the many things we can already do rather easily to reduce our encounters with NullPointerException, one particular easy thing to do is to apply String.valueOf(Object) when appropriate. The String.valueOf(Object) method, as its Javadoc-generated documentation states, returns "null" if the passed in object is null and returns the results on the passed-in Object's toString() call if the passed-in Object is not null. In other words, String.valueOf(String) does the null checking for you.

The use of String.valueOf(Object) is particularly useful when implementing toString methods on custom classes. Because most toString implementations provide the class's data members in String format, String.valueOf(Object) is a natural fit. All Java objects based on classes that extend Object provide a toString() implementation even if it is simply their parent's (or even Object's) implementation of toString(). However, if a member class implements toString but the member itself is null rather than an instance of the class, then the toString() does no good (and actually leads to a NullPointerException when called).

This is demonstrated with the following example code.

StringHandlingExample.java


package dustin.examples;

import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Logger;

/**
* Example class demonstrating use of String representations available through
* implicit String, toString(), and String.valueOf().
*/
public class StringHandlingExample
{
private static final String NEW_LINE = System.getProperty("line.separator");

/** Using java.util.logging. */
private static Logger LOGGER = Logger.getLogger(
StringHandlingExample.class.getName());

/**
* Main function for running tests/demonstrations.
*
* @param arguments Command-line arguments; none anticipated.
*/
public static void main(final String[] arguments)
{
printHeader("String representation of direct Strings", System.out);
final PersonName personName = new PersonName("Flintstone", null);
System.out.println("Person's Name [DIRECT]: " + personName);
System.out.println("Person's Name [TOSTRING]: " + personName.toString());
System.out.println("Person's Name [STRING.VALUEOF]: " + String.valueOf(personName));
printBlankLine(System.out);

printHeader("String representation of non-null complex object", System.out);
final Person personOne = new Person(personName);
System.out.println("Person One [DIRECT]: " + personOne);
System.out.println("Person One [TOSTRING]: " + personOne.toString());
System.out.println("Person One [STRING.VALUEOF]: " + String.valueOf(personOne));
printBlankLine(System.out);

printHeader("String representation of null complex object", System.out);
final Person personTwo = new Person(null);
System.out.println("Person Two [DIRECT]: " + personTwo);
System.out.println("Person Two [TOSTRING]: " + personTwo.toString());
System.out.println("Person Two [STRING.VALUEOF]: " + String.valueOf(personTwo));
printBlankLine(System.out);
}

public static void printHeader(final String message, final OutputStream out)
{
final String headerSeparator =
"====================================================================";

try
{
out.write((headerSeparator + NEW_LINE + message + NEW_LINE).getBytes());
out.write((headerSeparator + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
System.out.println(headerSeparator);
System.out.println(message);
System.out.println(headerSeparator);
LOGGER.warning("Could not write header information to provided OutputStream.");
}
}

public static void printBlankLine(final OutputStream out)
{
try
{
out.write(NEW_LINE.getBytes());
}
catch (IOException ioEx)
{
System.out.println(NEW_LINE);
LOGGER.warning("Could not write blank line to provided OutputStream.");
}
}

/**
* Class upon which to call toString.
*/
private static class PersonName
{
private String lastName;
private String firstName;

public PersonName(final String newLastName, final String newFirstName)
{
lastName = newLastName;
firstName = newFirstName;
}

/**
* Provide String representation of me.
*
* @return My String representation.
*/
@Override
public String toString()
{
return firstName + " " + lastName;
}
}

private static class Person
{
private PersonName name;

public Person(final PersonName newName)
{
name = newName;
}

/**
* Provide String representation of me.
*
* @return My String representation.
*/
public String toString()
{
// Don't use -- leads to compiler time error (incompatible types)
//return name;

// Don't use -- can lead to runtime error (NullPointerException)
//return name.toString();

// It's all good
return String.valueOf(name);
}
}
}


The above code can be used to demonstrate building of a toString method on a complex object and how its behaves when called by an owning class. The method of most interest is at the bottom of the code shown above. Two return values are commented out because of problems associated with them. The final example, using String.valueOf(Object) is NOT commented out because it works the best each time it is run whether or not the complex PersonName object is null. The next three images show the output for each of these presentations of the Person objects' String representations.

String Value from Complex Object - Compile-time Error




String Value from Complex Object toString() - Potential Runtime NullPointerException



String Value from Complex Object String.valueOf() - Nulls Handled Gracefully




Using String.valueOf(Object) in toString() implementations can be especially beneficial because we often use the toString() method when debugging and the last thing we need in such cases is another exception encountered while trying to see the current state of our data. Of course, one can also implement toString() methods with one's own checks for null or, even better, one can use something like ToStringBuilder. However, the availability of String.valueOf(Object) is certainly something worth keeping in mind and is something I find myself using fairly often. Many of us have found fewer lines of code to generally be more clear and String.valueOf(Object) can be much more clear than explicitly checking an object for null before invoking its toString() implementation.

Finally, the String class provides many overloaded valueOf methods. In addition to the version that was the focus of this blog post (accepts an Object), the other overloaded versions of valueOf accept primitive data types and arrays of primitive data types.


Conclusion

Regardless of what the future brings in terms of improved null handling in Java, there are many tactics we can take today to reduce the unwanted (sometimes we actually do want them thrown!) occurrences of NullPointerException. One of these is to use String.valueOf(Object) when appropriate.


Additional Resources