tags:

views:

2434

answers:

8

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 be "unknown", that is, not sure which year the document is created.

Therefore, a nullable int type as in C# will be well suited. However, Java does not have a nullable feature as C# has.

I have two options but I don't like them both:

  1. Use java.lang.Integer instead of the primitive type int;
  2. Use -1 to present the "unknown" value

Does anyone have better options or ideas?

Update: My entity class will have tens of thousands of instances; therefore the overhead of java.lang.Integer might be too heavy for overall performance of the system.

A: 

Another option is to have a boolean flag that indicates whether or not your year value is valid. This flag being false would mean the year is "unknown."

Eddie
That won't be a primitive type
hhafez
boolean is a primitive type.
Peter Lawrey
+8  A: 

Using the Integer class here is probably what you want to do. The overhead associated with the object is most likely (though not necessarily) trivial to your applications overall responsiveness and performance.

Matthew Vines
A: 

What's wrong with java.lang.Integer? It's a reasonable solution, unless you're storing very large amounts of this value maybe.

If you wanted to use primitives, a -1 value would be a good solution as well. The only other option you have is using a separate boolean flag, like someone already suggested. Choose your poison :)

PS: damn you, I was trying to get away with a little white lie on the objects vs structs. My point was that it uses more memory, similar to the boolean flag method, although syntactically the nullable type is is nicer of course. Also, I wasn't sure someone with a Java background would know what I meant with a struct.

Thorarin
nullable types in c# are structs. They are not boxed.
Matthew Vines
Nullable values are not boxed in C# as I know. Correct me if I am wrong.
yinyueyouge
Its a really common misconception. I was guilty of it myself until just recently. But check out http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx The first sentence is "Nullable types are instances of the System.Nullable<T> struct."
Matthew Vines
+6  A: 

Your 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.

hhafez
...unless you want to be able to represent both BC and AD years with the schema. ;-)
Anders Lindahl
+1  A: 

You can use a regular int, but use a value such as Integer.MAX_VALUE or Integer.MIN_VALUE which are defined constants as your invalid date. It is also more obvious that -1 or a low negative value that it is invalid, it will certainly not look like a 4 digit date that we are used to seeing.

Kekoa
+4  A: 

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 -1. This basically amounts to lying, since -1 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.
}
Apocalisp
How is -1 not a year? 1 BC is a year, and you would write that as -1 as an integer. I'd say that Integer.MAX_VALUE is probably not a realistic value for an year for quite some time.
elmuerte
Right you are, it's 0 that isn't a year. But that's not the point. The point is that sentinel values lose meaning and defeat the type system.
Apocalisp
A: 

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.

Peter Lawrey
A: 

java.lang.Integer is reasonable for this case. And it already implemented Serializable, so you can save just only the year field down to the HDD and load it back.

Truong Ha