Tag Archives: exception

Optional: Java 8’s way to deal with null

For those who have been programming Java or C/C++ for any period of time will know one of the most annoying things is trying to debug a crash due accessing a null object. While the concept of null is needed to make a programming language work, deal with deviations from the normal ‘happy’ path including error handling, it doesn’t contribute towards implementing a solution. Yet we have to spend a fair portion of our time dealing with and protecting against null values to make robust software. Today we will take a look how Optional can improve our code in general followed by a quick look through its API.

Null is the default value for an uninitialised class member field or static object, we reassign back to null to free memory. It’s also used for sentinel values such as indicating no data. The problem is when we try to access a null value we get an exception. We are then left trying to work out whether the value was uninitialised and thus the fault of some other code, or whether it was a sentinel value our code didn’t handle properly. Sometimes this leads to the wrong fix being made or dithering over which fix to make. This code will probably look familiar:

public class ImportantData
{
  private Data fileData; // Not constructor initialised

  ...

  // Call first before using csvData
  public void load(String fname)
  {
    try
    {
       fileData = loadCSVFromFile(fname);
    }
    catch (IOException e)
    {
      // Should at least have:
      // System.err.println("Can't load " + fname);
    }
  }

...
}

This is the ‘I can’t work out how to handle this yet’ pattern. Often we do this sort of thing just to get code running because handling the error might not be trivial, not yet specified and/or we’re making a proof of concept. Such code becomes more likely in the agile ‘always demonstrable’ development model. When we try to build on this code it’s easy to forget revisiting the shortcuts and hard to find them again unless we consistently mark them. Worse is when the exception is being caught, but the handler is empty, with not even a message, so we get a silent failure. This is further compounded by Java’s rule on having to catch checked exceptions tempting us into a shortcut. Testing might not even highlight the problem because it’s an exception case and might need something else to go wrong before we get a failure.

If fileData mustn’t be null we should certainly do a check. We could use an assert, but that will be disabled in production. Unless space or time is at a premium it’s always better to be defensive. Better to catch a problem sooner rather than later as well as not allowing it to go on and mess something else up. Until Java 7 we would have had to do the following:

    try
    {
       fileData = loadCSVFromFile(fname);
    }
    catch (IOException e)
    {
      // Should at least have:
      // System.err.println("Can't load " + fname);
    }

    if (fileData == null)
    {
      throw new NullPointerException("fileData can't be null!");
    }

This will also help us with the silent IOException catch since fileData will also be null there.

In Java 7 we can go one better and replace the null test with the built in:

   Objects.requireNonNull(fileData, "fileData can't be null!");

This is shorter, documents our intention that fileData can’t be null and prevents a null object causing bother later in the code. There are two versions of requireNonNull, one with a message and one without which translate exactly to the older Java equivalent.

Java 8 added Optional to allow us to work better with nulls and distinguish between no result and uninitialised/an error occurred. Let’s change the code as follows:

public class ImportantData
{
  private Optional<Data> fileData; // Not constructor initialised

  ...

  // Call first before using csvData
  public void load(String fname)
  {
    // assume fileData is uninitialised at this point

    try
    {
       fileData = Optional.of(loadCSVFromFile(fname));
    }
    catch (IOException e)
    {
      // Should at least have:
      // System.err.println("Can't load " + fname);
    }

    Objects.requireNonNull(fileData, "fileData can't be null!");
  }

...
}

Now we’re using an Optional to wrap our Data object using Optional’s static ‘of’ method (Optionals can only be initialised using static methods). The ‘of’ method will throw a NullPointerException if we try to wrap a null. We might as well use this as a free safety check as the code will crash there and then. If we have to be more robust later we can search for Optional.of to locate all the places we need to be checking for NullPointerException.

Once we’re finally done with fileData and need to release to the garbage collector we can’t just change the contents of an Optional (as that cannot be reassigned), we need to change what fileData references. We might consider a special sentinel object to indicate it was freed rather than using null which could be mistaken [when debugging] for never initialised (i.e. load was never called).

Suppose it’s acceptable for loadCSVFromFIle to return null, perhaps to indicate an empty file. Without wrapping this with an Optional we can’t tell between an empty file, the file wasn’t found, or the file was corrupted, or load was never called. If we don’t handle those exceptions properly we have no way later to know the cause of fileData being null and whether it should have be worked with, or should have been handled earlier. Thus we’re not documenting our intentions, often leaving someone else to work out what we meant. This can lead to the wrong fix being made.

Optional helps with this problem but to wrap nulls we must replace

...
       fileData = Optional.of(loadCSVFromFile(fname));
...

with

...
       fileData = Optional.ofNullable(loadCSVFromFile(fname));
...

Since passing a null to Optional’s ‘of’ method throws a NullPointerException, we have to use ofNullable which also wraps nulls. Under the hood an Optional.empty() is returned if null is passed to it. We can now tell the difference between an uninitialised fileData (due to exceptions or load not getting called) and the case of the file lacking any data.

Note: The example assumed that we couldn’t change loadCSVFromFile, but if we could we’d return the Optional from that rather than wrapping it afterwards. This will also save the user of the API from having to decide whether to wrap with ‘of’ or ofNullable.

Optional allows us to work with null objects easier as there are useful supporting functions reducing the boiler-plate ‘if (object != null) { …. ‘ that can litter code making it hard to follow.

Let’s now have a look at Optional’s API. Note there are also specialised Optionals: OptionalInt, OptionalDouble and OptionalLong whose APIs are very similiar. First we’ll start with creating (wrapping objects) and unwrapping them:

public static void main(String[] args)
{
    Optional<String> opt = Optional.of("hello");
    System.out.println("Test1: " + opt.get());

    try
    {
        Optional.of(null);
    }
    catch (NullPointerException e)
    {
        System.out.println(
           "Test2: Can't wrap a null object with of");
    }

    Optional<String> optNull = Optional.ofNullable(null);

    try
    {
        System.out.println(optNull.get());
    }
    catch (NoSuchElementException e)
    {
        System.out.println(
           "Test3: Can't unwrap a null object with get");
    }

    Optional<String> optEmpty = Optional.empty();

    try
    {
        System.out.println(optEmpty.get());
    }
    catch (NoSuchElementException e)
    {
        System.out.println(
           "Test4: Can't unwrap an empty Optional with get");
    }
}

There are four tests above:

1. The first shows the wrapping of an object which we do by calling the static ‘of’ method with object we wish to wrap then retrieving with get (getAs<type> in the specialised Optionals).
2. The second shows that we can’t wrap a null object with ‘of’ and if we try we get a NullPointerException. Thus ‘of’ should be used when we’re sure that a null is not possible or we wish to throw a NullPointerException if it is. If null is allowable we must use ofNullable instead.
3. & 4. The third and fourth are actually the same case since when ofNullable wraps a null a Optional.empty() is returned. We can also call the empty method directly. These tests show if the get method is used to unwrap Optional.empty() it will throw a NoSuchElementException.

One thing to note is the specialised versions (e.g. OptionalInt) do not have an ofNullable, although we can still do a test and manually get an OptionalInt.empty() if we want. Correspondingly that API works with int and not Integer.

Since we may need to check whether an Optional is empty or not, we can use the isPresent() test for this. The API explicitly states we should never do a == check against Optional.empty() since it can’t be guaranteed to be a singleton.

If we want to unwrap an Optional which may be null we should use orElse instead to give it a default value (which can be null).

public class OptionalTest2
{
        public static void main(String[] args)
        {
                Optional<String> opt = Optional.of("found");
                System.out.println(opt.isPresent());
                System.out.println(opt.orElse("not found"));

                Optional<String> optNull = Optional.ofNullable(null);
                System.out.println(optNull.isPresent());
                System.out.println(optNull.orElse("default"));

                Optional<String> optEmpty = Optional.empty();
                System.out.println(optEmpty.isPresent());
                System.out.println(optEmpty.orElse("default"));
        }
}

In addition to the code supplying a default value explicitly using orElse, we can call orElseGet to get a value from a supplier. There is also orElseThrow in which the supplier passed will supply an appropriate exception, and also an ifPresent method that passing the value to a supplier only if the Optional is wrapping a value. The next example demonstrates these:

public class OptionalTest3
{
	private static class MySupplier implements Supplier<String>
	{
		@Override
		public String get()
		{
			return "Supplier returned this";
		}
	}

	private static class MyExceptionSupplier implements
			Supplier<IllegalArgumentException>
	{
		@Override
		public IllegalArgumentException get()
		{
			return new IllegalArgumentException();
		}
	}

	private static class MyConsumer implements Consumer<String>
	{
		@Override
		public void accept(String t)
		{
			System.out.println("Consumed: " + t);
		}
	}

	public static void main(String[] args)
	{
		Optional<String> opt = Optional.of("found");
		System.out.println(opt.orElseGet(new MySupplier()));
		System.out.println(opt.orElseThrow(
                                         new MyExceptionSupplier()));
		opt.ifPresent(new MyConsumer());

		Optional<String> optNull = Optional.ofNullable(null);
		System.out.println(optNull.orElseGet(new MySupplier()));

		try
		{
			System.out.println(optNull.orElseThrow(
                                         new MyExceptionSupplier()));
		}
		catch (IllegalArgumentException e)
		{
			System.out.println("Exception caught");
		}

		// This one won't use the consumer
		optNull.ifPresent(new MyConsumer());
	}
}

Having to retrieve and check for values being present in this way, although initially tedious, makes us think more about what to do if values are null. It’s at least shorter that not using Optional.

Note that in latest example if we were wrapping say Integer instead of String, we can’t use IntSupplier or IntConsumer. This is because orElseGet and ifPresent of Optional require a type that extends or is super to an Integer respectively (including Integer or course). IntSupplier and IntConsumer do not extend Supplier and Consumer so we cannot substitute them. The specialised OptionalInt does take a IntSupplier and IntConsumer though.

There are a few useful functional methods (which surprisingly haven’t been added to the wrapper classes or Number): filter, map and flatMap. FlatMap handles the case where the mapping function already returns an Optional and so doesn’t wrap it again. Conversely Optional’s map will wrap whatever the mapping function returns.

Filter returns Optional.empty() if the predicate doesn’t match. If the Optional was already empty the predicate is not checked, although this shouldn’t concern us because Predicates should be just logical tests, and not have side-effects.

Here’s a quick run through:

public static void main(String args[])
{
    Optional<String> hiMsg = Optional.of("hi");

    Optional<String> hiThereMsg = hiMsg.map(x -> x + " there!");

    System.out.println(hiMsg.get()); // Original

    System.out.println(hiThereMsg.get()); // Mapped

    System.out.println(hiThereMsg.filter(x -> x.equals("hi there!"))
				 .orElse("Bye!"));

    // Filter test fails returning Optional.empty()
    System.out.println(hiThereMsg.filter(x -> x.equals("yo there!"))
				.orElse("Bye!"));

    // The Optional gets wrapped
    Optional<Optional<String>> byeMessage = hiThereMsg
                                 .map(x -> Optional.of("Bye bye!"));

    // No extra wrapping
    Optional<String> byeMessage2 = hiThereMsg
                             .flatMap(x -> Optional.of("Bye bye!"));

    System.out.println(byeMessage.get().get());
    System.out.println(byeMessage2.get());

    // This would be an error since the
    // mapping has to return Optional
    // hiThereMsg.flatMap(x -> "Bye bye!");

    // We can change the wrapped type
    Optional<Integer> five = hiThereMsg.map(x -> 5);
    System.out.println(five.get());

    Optional<Integer> six = hiThereMsg.flatMap(x -> Optional.of(6));
    System.out.println(six.get());
}

Finally a word of warning from the Java documentation itself: ‘This is a value-based class; use of identity-sensitive operations (including reference equality ==), identity hash code, or synchronization on instances of Optional may have unpredictable results and should be avoided.’ In short don’t try to use ==, hashCode or synchronized on Optional. Normal .equals can be used but you if you’re expecting a match then the object you are comparing against will also need to be an Optional. If both Optionals are Optional.empty(), that is considered a match.

More will said soon on how Optional fits in with the new functional programming features.

Advertisements

Finite Sequence Generators in Java 8 – Part 2

In the last couple of articles we looked at generators. First we looked at ways of generating an infinite sequence. In the second we saw a way of generating a finite sequence. Let’s look at a few more aspects before we move on.

In the finite sequence article, we saw that unless we wanted to limit ourselves to a certain number of values we couldn’t use generate and iterate in a simple manner. This was because there was no way of indicating a stop condition. Limit is fine if we know how many values we need, but not if we don’t. If we use limit we’d have to create a new stream to get further values. There are a couple of other methods we could use for generating finite sequences without having to resort to using Iterable.

Let’s go back to our die throwing SixGame example from the last article. Instead of using an Iterator/Iterable, we’ll use an IntSupplier coupled with IntStream’s generate method. If any of that is new to you, then first review the article on generators with infinite sequences. We’re going to attempt (and I’m not saying this is good practice) to stop generating when we get a Six by throwing an exception:

public class SixGame
{
	public static class DieThrowSupplier implements IntSupplier
	{
		private Random rand = new Random(System.nanoTime());
		private boolean done = false;

		@Override
		public int getAsInt()
		{
			if (!done)
			{
				int dieThrow = Math.abs(rand.nextInt()) % 6 + 1;

				if (dieThrow == 6)
				{
					done = true;
				}

				return dieThrow;
			}
			else
			{
				throw new NoSuchElementException();
			}
		}
	}

	public static void main(String args[])
	{
		DieThrowSupplier dieThrows = new DieThrowSupplier();

		IntStream myStream = IntStream.generate(dieThrows);
		
		try
		{
			myStream.mapToObj(i -> "You threw a " + i).forEach(
					System.out::println);
		}
		catch (NoSuchElementException e)
		{
			// Escaped
		}
	}
}

Something here that’s new is the mapToObj call. We’re starting out with an IntStream, but we want to create a message which is a String. Thus we need to change the ‘shape’ of the stream from Integer to Object (there is no special String stream) and we can do that with mapToObj. It works like map, but instead of expecting an Integer being returned from the function, it expects an Object.

We have to catch the exception, but luckily (or perhaps sloppily given this is a demonstration) we are using a side-effect to do something with the string we generate: printing in forEach. Once we go parallel though we need to remove side effects. Although we’ve not covered it yet, what we need to do is collect the results from the stream, perhaps in a list, and then perform the printing outside of the stream chain. Although this seems a lot for our simple game, getting streams to work properly in parallel is one of the more difficult tasks that we’re going to have to master eventually.

Our problem in the parallel world is going to be that we’re collecting, but we need to assign that collection to something when the stream is done. Try changing the try/catch code to the broken:

            List<String> l = null;

            try
            {
                    l = myStream.parallel().mapToObj(i -> "You threw a " + i)
                                           .collect(Collectors.toList());
            }
            catch (NoSuchElementException e)
            {
                    // Escaped
            }

            l.stream().forEach(System.out::println);

Nothing gets printed this time, and we crash with a NullPointerException. Given we throw an exception during the stream which we catch after the assignment and not as part of the stream, the assignment never happens. Thus the list, l, stays null. We went through all the motions and got nothing for our troubles. Perhaps we could try making special collectors to handle exceptions, but given an exception is almost certainly a side-effect we should avoid these when going parallel. I can also imagine that catching exception outside of a stream and hoping we still get all the results might be quite flaky as we’re relying on the implementation to make it work. Implementations change, and other implementations come along. My verdict is – unless Oracle say otherwise, is avoid.

We also discussed that we wanted to avoid implementing a whole spliterator if there was another way available. To recap, a spliterator is an iterator that can be split into batches of work and is what drives streams. Getting that right isn’t trivial. We saw that we couldn’t get access to override InfiniteSupplyingSpliterator in order to make a version we could terminate. However, there exists a spliterator that is just missing tryAdvance which we use to inject the next value into the stream and indicate when we’re done. This is AbstractSpliterator, in particular AbstractIntSpliterator, which we can extend. Let’s have a look at our game using one of those:

public class SixGame
{
	public static class DieThrowSpliterator extends
			Spliterators.AbstractIntSpliterator
	{
		private Random rand = new Random(System.nanoTime());
		private boolean done = false;

		protected DieThrowSpliterator()
		{
			super(Long.MAX_VALUE, 0);
		}

		private int rollDie()
		{
			int dieThrow = Math.abs(rand.nextInt()) % 6 + 1;

			if (dieThrow == 6)
			{
				done = true;
			}

			return dieThrow;
		}

		@Override
		public boolean tryAdvance(IntConsumer action)
		{
			if (action == null)
			{
				throw new NullPointerException();
			}
			
			if (done)
			{
				return false;
			}

			action.accept(rollDie());

			return true;
		}

		@Override
		public boolean tryAdvance(Consumer<? super Integer> action)
		{
			if (action == null)
 			{
				throw new NullPointerException();
  			}

  			if (done)
  			{
				return false;
  			}

  			action.accept(rollDie());

  			return true;
		}
	}

	public static void main(String args[])
	{
		Stream<Integer> stream = StreamSupport.stream
					(new DieThrowSpliterator(), false);

		stream.map(i -> "You threw a " + i)
	              .forEach(System.out::println);
	}
}

First notice that we are creating the stream the same way we did when using an Iterable, but instead we are creating a spliterator which we pass to the stream. The second thing to notice is that we have to implement two tryAdvance functions. These take Consumers which will use our value. The first is a true IntConsumer, where as the second is a Consumer of any type which can hold an Integer (Object, Number and Integer). I’ve kept the null check used in other spliterators. If we’re already done, we can return false, otherwise pass a roll to the action and return true. The parent constructor of our spliterator takes two values, the first being how many values we expect (we don’t know) and flags for characteristics of the spliterator (0 being none of them).

No doubt we could continue the discussion on generation, particularly as we now have several ways to solve problems. For now we’ll move on and look at a few more aspects of Java 8 functional programming and lambda expressions.