It is said that when input parameter is null, compareTo() should throw a NullPointerException. However, I am implementing a class which needs to compare fields with the type of String. These fields need not to be mandatory. I wonder in this case,
1) What should I return when the input is null? Should any not-null strings lexicographically bigger or smaller than null?
and
2) If this is considered bad practice, is there any supporting arguments? Should I force the user to use empty strings instead? If using empty string, won't that confuse the case in which the field is not applicable and the case in which the field is empty? And if exception must be thrown, then except from warning the user in the manual, what else could/shall I do?
EDIT: I might not express myself clearly here, but in the program I am implementing, the strings that could be null are all fields or a class, which should not be null. In other words, the objects comparedTo() uses could not be null, just their private fields could be. So in this case, I believe if I implement compareTo() properly, it would not violate the transitive requirement since classes with null fields would be considered the same always. Am I right or am I interpreting this wrong?
Thank you all for the answers!
From javadoc for
Comparable
You need to decide if null is greater-than or less-than to a non-null value. You can design
compareTo
to meets the needs of your class's natural ordering, thus it is not bad practice.Yes, there is no problem allowing
null
for instance fields - just make sure its sorting order is defined. Most natural would be putting it either before or after all real strings, but you could do anything here, just do it consistently. (For example, you could sortnull
like"null"
.)Here is an example implementation for a single member:
Please note that the specification of Comparable.compareTo() only has a constraint for
o.compareTo(null)
(which should behave just like- null.compareTo(o)
, i.e. throw a NullPointerException), but not about hownull
fields are handled (it doesn't mention fields at all, so a class could return whatever it wants, as long as the antisymmetry, reflexivity and transitivity is ensured).It would be a bad practice to not throw an exception because it violates the
transitiveantisymmetric nature of compareTo.From Comparable.compareTo documentation:
More importantly, it's a bad idea to use compareTo on your objects to compare them with strings, for the same reason:
sign(obj.compareTo(str)) != -sign(str.compareTo(obj))
. Implement a custom Comparator and do whatever you want in it.Because the documentation of
compareTo
states that it should throw aNullPointerException
, you should follow those guidelines so your implementation is consistent with the interface documentation. This also handles the questions of whether or not non-null strings are lexicographically smaller or bigger thannull
.You have a couple of options on how to handle this. If empty and not-applicable are different, then you should probably wrap the string field in your own field class. For example, say you could create a type of MyField that might have an
isApplicable
method, which indicates if the field is applicable to this case (or something similar). Or you could rethink your design and be sure that an empty string and N/A really are two different things. If they are, you do need a way to differentiate between the two.