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

zw3*_*324 18 java string null nullpointerexception compareto

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

1)当输入为空时我应该返回什么?任何非空字符串在字典上是大于还是小于null?

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

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

谢谢大家的答案!

Bal*_*a R 25

来自javadoc Comparable

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


Paŭ*_*ann 14

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

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

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

请注意,Comparable.compareTo()的规范只有一个约束o.compareTo(null)(它应该表现得就像- null.compareTo(o)抛出一个NullPointerException),但不是关于如何null处理字段的约束(它根本没有提到字段,所以一个类可以只要确保反对称性,反身性和传递性,就可以回报任何想要的东西.

  • @EJP:`compareTo`的规范没有说明如何(甚至是否)比较对象的实例字段. (2认同)
  • 是的,但在这个问题中(至少在我的回答之前编辑之后),它不是将对象与'null`进行比较,而是将对象与另一个对象进行比较,其中一个对象具有"null"字段.`compareTo`规范对此没有任何说明. (2认同)
  • @EJP Paulo在这里是正确的.当foo1.compareTo(foo2)`发现`foo2!= null`但是`foo2.someField == null`时,原始问题会询问该怎么做.规范只规定`foo == null`时的行为. (2认同)

yka*_*ich 7

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

来自Comparable.compareTo文档:

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

实现者还必须确保关系是传递的:(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并在其中执行任何操作.