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
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.
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;
}
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.
}
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.
You could use the @Nullable annotation if using java 7
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; }
}