Что должна возвращать int compareTo (), когда строка параметра равна нулю? - PullRequest
17 голосов
/ 07 июня 2011

Говорят, что когда входной параметр равен нулю, compareTo () должен выдать исключение NullPointerException. Тем не менее, я реализую класс, который должен сравнивать поля с типом String. Эти поля не должны быть обязательными. Интересно в этом случае

1) Что я должен вернуть, когда входной сигнал равен нулю? Должны ли какие-либо ненулевые строки лексикографически больше или меньше нуля?

и

2) Если это считается плохой практикой, есть ли дополнительные аргументы? Должен ли я заставить пользователя использовать пустые строки вместо этого? Если используется пустая строка, не перепутает ли это случай, когда поле не применимо, и случай, когда поле пустое? И если должно быть выдано исключение, то, кроме предупреждения пользователя в руководстве, что еще я мог / должен сделать?

РЕДАКТИРОВАТЬ: Я мог бы не выразить себя ясно здесь, но в программе, которую я реализую, строки, которые могут быть нулевыми, являются всеми полями или классом, который не должен быть нулевым. Другими словами, объекты сравниваемые () не могут быть нулевыми, могут быть только их частные поля. Так что в этом случае, я считаю, что если я правильно реализую compareTo (), это не нарушит транзитивное требование, поскольку классы с нулевыми полями всегда будут считаться одинаковыми. Я прав или я неправильно это понимаю?

Спасибо всем за ответы!

Ответы [ 5 ]

25 голосов
/ 07 июня 2011

Из Javadoc для Comparable

Обратите внимание, что ноль не является экземпляром любой класс и e.compareTo (ноль) должен выдать исключение NullPointerException хотя e.equals (null) возвращает ложь.

13 голосов
/ 07 июня 2011

Да, нет проблем с разрешением 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);
   }
}

Обратите внимание, что спецификация Comparable.compareTo() имеет ограничение только для o.compareTo(null) (которое должно вести себя так же, как - null.compareTo(o), то есть генерировать исключение NullPointerException), но не о том, как обрабатываются поля null (он вообще не упоминает поля, поэтому класс можетвернуть все, что захочет, при условии, что обеспечивается антисимметрия, рефлексивность и транзитивность).

7 голосов
/ 07 июня 2011

Было бы плохой практикой не генерировать исключение, потому что оно нарушает транзитивный антисимметричный характер сравнения.

С Comparable.compareTo документация:

Разработчик должен обеспечить sgn (x.compareTo (y)) == -sgn (y.compareTo (x)) для всех x и y.(Это означает, что x.compareTo (y) должно выдать исключение, если y.compareTo (x) выдает исключение.)

Разработчик также должен убедиться, что отношение транзитивно: (x.compareTo (y)> 0 && y.compareTo (z)> 0) подразумевает x.compareTo (z)> 0.

Наконец, разработчик должен убедиться, что x.compareTo (y) == 0 подразумевает, что sgn (x.compareTo (z)) == sgn (y.compareTo (z)) для всех z.

Что еще более важно, это плохая идея - использовать CompareTo на ваших объектах для сравнения их со строками по той же причине: sign(obj.compareTo(str)) != -sign(str.compareTo(obj)).Реализуйте пользовательский Comparator и делайте в нем все, что вы хотите.

3 голосов
/ 07 июня 2011

Вам необходимо решить, является ли значение NULL больше или меньше, чем ненулевое значение. Вы можете разработать compareTo в соответствии с потребностями естественного порядка вашего класса, таким образом, это не плохая практика.

3 голосов
/ 07 июня 2011

Поскольку в документации compareTo указано, что она должна выдавать NullPointerException, вы должны следовать этим рекомендациям, чтобы ваша реализация соответствовала документации интерфейса. Это также решает вопрос о том, являются ли ненулевые строки лексикографически меньше или больше null.

У вас есть несколько вариантов того, как справиться с этим. Если пустые и неприменимые значения отличаются, то вам, вероятно, следует заключить строковое поле в свой собственный класс поля. Например, допустим, вы можете создать тип MyField, который может иметь метод isApplicable, который указывает, применимо ли поле к этому случаю (или что-то подобное). Или вы могли бы переосмыслить свой дизайн и быть уверенным, что пустая строка и N / A действительно две разные вещи. Если это так, вам нужен способ провести различие между ними.

...