How to present the nullable primitive type int in Java?

后端 未结 13 964
灰色年华
灰色年华 2020-12-03 13:29

I am designing an entity class which has a field named \"documentYear\", which might have unsigned integer values such as 1999, 2006, etc. Meanwhile, this field might also b

相关标签:
13条回答
  • 2020-12-03 13:44

    You're going to have to either ditch the primitive type or use some arbitrary int value as your "invalid year".

    A negative value is actually a good choice since there is little chance of having a valid year that would cause an integer overflow and there is no valid negative year.

    0 讨论(0)
  • 2020-12-03 13:45

    Another option might be to use a special value internally (-1 or Integer.MIN_VALUE or similar), but expose the integer as two methods:

    hasValue() {
        return (internalValue != -1);
    }
    
    getValue() {
        if (internalValue == -1) {
            throw new IllegalStateException(
                "Check hasValue() before calling getValue().");
        }
        return internalValue;
    }
    
    0 讨论(0)
  • 2020-12-03 13:51

    Tens of thousands of instances of Integer is not a lot. Consider expending a few hundred kilobytes rather than optimise prematurely. It's a small price to pay for correctness.

    Beware of using sentinel values like null or 0. This basically amounts to lying, since 0 is not a year, and null is not an integer. A common source of bugs, especially if you at some point are not the only maintainer of the software.

    Consider using a type-safe null like Option, sometimes known as Maybe. Popular in languages like Scala and Haskell, this is like a container that has one or zero elements. Your field would have the type Option<Integer>, which advertises the optional nature of your year field to the type system and forces other code to deal with possibly missing years.

    Here's a library that includes the Option type.

    Here's how you would call your code if you were using it:

    partyLikeIts.setDocumentYear(Option.some(1999));
    
    Option<Integer> y = doc.getDocumentYear();
    if (y.isSome())
       // This doc has a year
    else
       // This doc has no year
    
    for (Integer year: y) {
      // This code only executed if the document has a year.
    }
    
    0 讨论(0)
  • 2020-12-03 13:51

    If you have an integer and are concerned that an arbitrary value for null might be confused with a real value, you could use long instead. It is more efficient than using an Integer and Long.MIN_VALUE is no where near any valid int value.

    0 讨论(0)
  • 2020-12-03 13:51

    You could use the @Nullable annotation if using java 7

    0 讨论(0)
  • 2020-12-03 13:52

    For completeness, another option (definitely not the most efficient), is to use a wrapper class Year.

    class Year {
        public int year;
        public Year(int year) { this.year = year; }
    }
    
    Year documentYear = null;
    documentYear = new Year(2013);
    

    Or, if it is more semantic, or you want multiple types of nullable ints (Other than Years), you can imitate C# Nullable primitives like so:

    class Int {
        public int value;
        public Int(int value) { this.value = value; }
        @Override 
        public String toString() { return value; }
    }
    
    0 讨论(0)
提交回复
热议问题