Sunday, June 20, 2010

Remove boilerplate with Guava

Guava describes itself as "Google's core Libraries for Java 1.5+". It is a superset of the Google Collections framework, along with other utilities, released as an open-source project under the Apache 2.0 license.

What I want to cover in this post are not Guava's major features, but rather some simple "shortcut" methods (each factoring a common Java idiom) that can make a developer's life easier.

To illustrate this, let's consider this simple method:
public void save(final String info, final File file) throws IOException {
  if (file == null) throw new NullPointerException("file should not be null");
  Writer writer = null;
  boolean threw = true;
  try {
    writer = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(file), Charset.forName("UTF-8")));
    String data = info == null ? "Nothing" : info;
    writer.write(data);
    threw = false;
  } finally {
    if (writer != null)
      try {
        writer.close();
      } catch (IOException e) {
        // Do not swallow original exception
        if (!threw) throw e;
      }
  }
}
Here is a version with the corresponding Guava methods:
public void save(final String info, final File file) throws IOException {
  Preconditions.checkNotNull(file, "file should not be null");
  Writer writer = null;
  boolean threw = true;
  try {
    writer = Files.newWriter(file, Charsets.UTF_8);
    writer.write(Objects.firstNonNull(info, "Nothing"));
    threw = false;
  } finally {
    Closeables.close(writer, threw);
  }
}
Actually, there is even simpler, since we are only writing one string to the file:
public void save(final String info, final File file) throws IOException {
  Preconditions.checkNotNull(file, "file should not be null");
  Files.write(Objects.firstNonNull(info, "Nothing"), file, Charsets.UTF_8);
}
Optionally, you can also static import everything (which increases readability but makes the origin of the methods less obvious — the choice is a matter of personal taste):
public void save(final String info, final File file) throws IOException {
  checkNotNull(file, "file should not be null");
  write(firstNonNull(info, "Nothing"), file, UTF_8);
}
That's it. Nothing groundbreaking really, but I like how this makes the code more expressive, focusing on what you do rather than how you do it. Guava has a myriad of these utilities (look for static methods in the classes that have a plural name: Lists, Strings, Resources...).

0 comments: