当参数字符串为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级自然顺序的需求,因此这不是一种不好的做法。