What should int compareTo() return when the parameter string is null?

跟風遠走 提交于 2019-11-29 01:22:51

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 sort null like "null".)

Here is an example implementation for a single member:

class Example implements Comparable<Example> {

   @Nullable
   private String member;

   // TODO: getter, setter, constructor, ...

   public int compareTo(Example that) {
      if(this.member == null)
         if(that.member == null)
            return 0; //equal
         else
            return -1; // null is before other strings
       else // this.member != null
         if(that.member == null)
            return 1;  // all other strings are after null
         else
            return this.member.compareTo(that.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 how null 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).

From javadoc for Comparable

Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.

It would be a bad practice to not throw an exception because it violates the transitive antisymmetric nature of compareTo.

From Comparable.compareTo documentation:

The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)

The implementor must also ensure that the relation is transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.

Finally, the implementor must ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.

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 a NullPointerException, 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 than null.

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!