Thursday, September 1, 2011

Checking for Null or Empty or White Space Only String in Java

.NET Framework 4 introduces a new method on its String class called IsNullOrWhiteSpace that checks whether a provided String is null, empty, or consists only of "white space." This handy method is in addition to the method IsNullOrEmpty that has been available since .NET 2. These potentially very useful (and commonly used) methods are not part of Java's standard JDK String, but in this post I look at how Apache Commons Lang and Guava provide methods similar to these or from which methods similar to these can be easily written.

A typical "standard Java" approach for detecting whether a String is null, is empty, or consists solely of white space is as shown in the next code listing.

Java Approach
/**
 * Demonstrate checking for String that is not null, not empty, and not white
 * space only using standard Java classes.
 *
 * @param string String to be checked for not null, not empty, and not white
 *    space only.
 * @return {@code true} if provided String is not null, is not empty, and
 *    has at least one character that is not considered white space.
 */
public static boolean isNotNullNotEmptyNotWhiteSpaceOnlyByJava(
   final String string)
{
   return string != null && !string.isEmpty() && !string.trim().isEmpty();
}

In the above example, one might compare length of Strings rather than call the isEmpty() method. There are other approaches as well including using regular expressions. Also, the code could be made more concise by not having the individual check for emptiness and simply doing that via the trim().isEmpty() call.

The Google Guava library can also be used effectively for determining a non-null, not empty String with at least one non-whitespace character. An example of that is shown next.

Guava Approach
// import com.google.common.base.Strings;
/**
 * Demonstrate checking for String that is not null, not empty, and not white
 * space only using Guava.
 *
 * @param string String to be checked for not null, not empty, and not white
 *    space only.
 * @return {@code true} if provided String is not null, is not empty, and
 *    has at least one character that is not considered white space.
 */
public static boolean isNotNullNotEmptyNotWhiteSpaceOnlyByGuava(final String string)
{
   return !Strings.isNullOrEmpty(string) && !string.trim().isEmpty();
}

The Guava approach above uses the "standard Java" approach for determining that the String is not white space only. However, Guava provides the convenient Strings.isNullOrEmpty(String) static method for determining if a given String is null or empty.

The example using Apache Commons Lang is simplest and most concise approach as depicted in the next code listing.

Apache Commons Lang Approach
// import org.apache.commons.lang.StringUtils;
/**
 * Demonstrate checking for String that is not null, not empty, and not white
 * space only using Apache Commons Lang classes.
 *
 * @param string String to be checked for not null, not empty, and not white
 *    space only.
 * @return {@code true} if provided String is not null, is not empty, and
 *    has at least one character that is not considered white space.
 */
public static boolean isNotNullNotEmptyNotWhiteSpaceOnlyByCommons(
   final String string)
{
   return StringUtils.isNotBlank(string);
}

With Apache Commons Lang, one simple call does it all! The StringUtils.isNotBlank(String) static method does exactly what we wanted in this particular case: check a String to ensure it is not null, not empty, and not white space only. Its Javadoc documentation says as much: 'Checks if a String is not empty (""), not null and not whitespace only.'

The above approaches and variations on the above approaches can be used in Java to determine if a String is not null, not empty, and not white space only. They are easy to employ and the Apache Commons Lang approach is particularly concise. However, it would be nice to have this support as a standard part of the Java String. It is difficult for me to finish a post without talking about Groovy, so now I transition to the ability to use Groovy's dynamic support to "add" methods to Java's String class to support this check.

The Groovy code in the next code listing shows how an instance method could be added to String to check for these conditions. In this case, I'm borrowing from Apache Commons Lang's name for the method and using isNotBlank() for the injected method name.

Using metaClass.methodMissing to 'Add' isNotBlank() Method to String
java.lang.String.metaClass.methodMissing=
{ String name, args ->
   if (name == "isNotBlank")
   {
      // Do NOT need to check for null because this method could not have been
      // invoked on a null String. Groovy's GDK extension of String has the
      // isAllWhitespace() method that returns {@code true} for all white space
      // including empty String.
      return !delegate.isAllWhitespace()
   }
}

The above Groovy snippet will inject an "isNotBlank()" method on String instances when invocations of a method of that name are not resolved (missing method). I don't have a null check because an instance method, by its nature, will only work on a non-null instance. The reason the methods discussed previously checked for null is that they were static methods working on a provided instance (and not themselves). With Groovy clients and the safe navigation operator, this is not as much of a deal-breaker as it might be in Java. The example above also demonstrates a method that Groovy's GDK extension of String provides: isAllWhitespace().

An advantage of the above instance-level approach is that we can ask the String itself if it is empty of white space. As you may have noticed, one did not need to intercept String in Groovy to implement this method as the isAllWhitespace() method Groovy provides on the GDK extension of String actually counts an empty String as being all white space.

Suppose that we want to use a static method in Groovy like the Java examples shown earlier so that null can be handled as well. Because this is Groovy, we could simply use the Apache Commons Lang class or the Guava class just as we did in Java. For realistic purposes, that would be a good approach. But for showing off Groovy's grooviness, the next approach is preferable. In this case, a new static method is defined on String that implements the check we have seen above. This enables Groovy client code to call a static method directly on String itself for the check.

Using metaClass.static to 'Add' New Static Method to String
java.lang.String.metaClass.static.isNotNullNotEmptyNotWhitespaceOnly=
{ String string ->
   return string != null && !string.isAllWhitespace()
}

This last example makes it possible to call String.isNotNullNotEmptyNotWhitespaceOnly(String) on any String from Groovy code to check it for being not null, not empty, and not white space only. It also demonstrates how to inject a static method into an existing object in Groovy.


Conclusion

It would be a minor added convenience if standard Java had a class and/or methods added to check Strings for more common conditions. Java 7 has added the Objects class for performing some very common functionality on Objects, so a new class called Strings or StringUtils might do the same thing for Java Strings.

4 comments:

Hadrien said...

Nice Summary, you could also mention a method from the Spring Framework :
StringUtils.hasText(String str) which actually does the opposite so you could use it in combination with "!"

Martijn Verburg said...

Just the sort of thing that could be suggested for Project Coin (for Java 8). Please do submit your idea to the coin-dev OpenJDK mailing list!

Dustin said...

Hadrien,

Thanks for mentioning StringUtils.hasText(String). That's another good example of a third-party Java library providing this common functionality.

Dustin

Dustin said...

Martijn,

I agree that this (and possibly other String-related functionality inspired by Guava's Strings, Apache Commons Lang's StringUtils, Spring's StringUtils, and Groovy's GDK String extension) could be a good candidate for Java 8.

Dustin