当参数字符串为null时,int compareTo()应该返回什么?

据说当input参数为null时,compareTo()应抛出NullPointerException。 但是,我正在实现一个需要将字段与String类型进行比较的类。 这些字段不必是强制性的。 我想知道在这种情况下,

1)当输入为空时我应该返回什么? 是否任何非空字符串按字典顺序大于或小于null?

2)如果这被认为是不好的做法,是否有任何支持性论点? 我应该强制用户使用空字符串吗? 如果使用空字符串,那不会混淆字段不适用的情况和字段为空的情况吗? 如果必须抛出exception,那么除了在手册中警告用户之外,还有什么可以/我应该做什么?

编辑:我可能不会在这里清楚地表达自己,但在我正在实现的程序中,可以为null的字符串是所有字段或类,不应该为null。 换句话说,comparisonTo()使用的对象不能为null,只有它们的私有字段可以。 所以在这种情况下,我相信如果我正确地实现了compareTo(),它就不会违反传递要求,因为具有空字段的类总是被认为是相同的。 我是对的还是我在解释这个错误?

谢谢大家的答案!

是的,允许null实例字段没有问题 – 只需确保定义其排序顺序。 最自然的是将它放在所有真正的琴弦之前或之后,但你可以在这里做任何事情,只要一贯地做。 (例如,您可以将null排序为"null" 。)

以下是单个成员的示例实现:

 class Example implements Comparable { @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); } } 

请注意,Comparable.compareTo()的规范只有o.compareTo(null)的约束(其行为应该像- null.compareTo(o) ),但不是关于如何处理null字段(它不是提到领域,所以只要确保反对称性,反身性和传递性,一个class级就可以回报任何想要的东西。

来自javadoc for Comparable

请注意,null不是任何类的实例,并且即使e.equals(null)返回false,e.compareTo(null)也应抛出NullPointerException。

不抛出exception是不好的做法,因为它违反了compareTo的传递反对称性质。

来自Comparable.compareTo文档:

实现者必须确保所有x和y的sgn(x.compareTo(y))== -sgn(y.compareTo(x))。 (这意味着如果y.compareTo(x)抛出exception,x.compareTo(y)必须抛出exception。)

实现者还必须确保关系是传递的:(x.compareTo(y)> 0 && y.compareTo(z)> 0)意味着x.compareTo(z)> 0。

最后,对于所有z,实现者必须确保x.compareTo(y)== 0意味着sgn(x.compareTo(z))== sgn(y.compareTo(z))。

更重要的是,在对象上使用compareTo将它们与字符串进行比较是一个坏主意,原因相同: sign(obj.compareTo(str)) != -sign(str.compareTo(obj)) 。 实现自定义Comparator并在其中执行任何操作。

因为compareTo的文档声明它应该抛出NullPointerException ,所以您应该遵循这些准则,以便您的实现与接口文档一致。 这也解决了非空字符串是否在字典上小于或大于null

你有几个选择如何处理这个问题。 如果为空且不适用不同,那么您应该将字符串字段包装在您自己的字段类中。 例如,假设您可以创建一种可能具有isApplicable方法的isApplicable类型,该方法指示该字段是否适用于此情况(或类似的情况)。 或者您可以重新考虑您的设计,并确保空字符串和N / A确实是两个不同的东西。 如果是,您需要一种方法来区分这两者。

您需要确定null是否大于或小于非null值。 您可以设计compareTo以满足您class级自然顺序的需求,因此这不是一种不好的做法。