7

I was reviewing a coworker's code, and noticed that he was using Integer objects instead of ints in some APIs (getters, setters, instance variables, and method parameters). When I asked him why, he told me it was because he wanted to use null to indicate an uninitialized state, because there was no good default value.

I feel conflicted. On one hand, this is a common practice with other objects (I know, Java 8 makes it better with Optional<T>). On the other hand, it seems that the chance of a NullPointerException is higher if API clients use autoboxing.

Is this a good coding practice?

    2 Answers 2

    4

    This is completely reliant on the problem domain and how the interface is used. I have written interfaces both ways.

    I have seen SOAP libraries not allow null values, making Integer completely unnecessary.

    On the flip side, I have used Integer for cached data (you specifically mention "instance variables" in your question, not just the API):

    public class Test implements Serializable { private transient Integer hash; public int hashCode() { if (hash == null) { hash = <time-consuming hash operation>; } return hash.intValue(); } } 

    In this case, the object is being used as a key in a HashMap so it makes sense to cache a hash value rather than recompute it over and over. Using Integer means I can say with 100% certainty that I have already computed the value or not (as opposed to String's sentinel value which in theory can produce a hash collision).

    If an API accepts Integer but assumes not null, that is a fail-fast scenario. It will throw a NullPointerException and should do so quickly. Client code using your API should encounter this exception rather quickly, making it easy to find and fix the bad data when testing.

    I recommend using Integer (maybe with Optional to make it clear) for optional data, and int when it is required.

    4
    • I agree with your answer but I don't understand the reference to String's sentinel value. What is that about?CommentedMar 11, 2016 at 21:22
    • @5gon12eder String uses a value of 0 to indicate there is no hash. It is possible for a string to hash to 0, so it would rehash each time.
      – user22815
      CommentedMar 11, 2016 at 21:37
    • Is this an implementation detail you've found out (for some implementation) or is it somehow required? I cannot find anything related to this here.CommentedMar 11, 2016 at 21:45
    • @5gon12eder implementation detail. Look at String.java.
      – user22815
      CommentedMar 11, 2016 at 21:46
    2

    Any value which can ever be null is a NullPointerException waiting to happen. Any code which checks those values need to do an additionally check for null, which is easy to forget for you and even easier to forget for any other users of your classes.

    For that reason whenever I have a value which can be intentionally unknown or absent, I use Optional<T> since Java 8.

    Note that using optional.get() returns NoSuchElementException on absent values which is only slightly more useful than a NullPointerException. Instead I prefer the pattern optional.ifPresent( [lambda-expression] );

    An alternative solution to avoid NullPointerExceptions is the Null Object Pattern. When you have an own class which can be null, also add a singleton which extends that class and represents an uninitialized or unknown instance of that class and which implements all public methods to behave gracefully.

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.