Сравнение равенства любым разумным способом?

Как мне реализовать это сравнение равенства, это разумный способ Java?

boolean x = (a == b) || (a.equals(b))

Я хочу убедиться, что содержимое обоих объектов равно, но null также в порядке, т.е. оба могут быть нулевыми и, таким образом, равны.

Обновление: просто для ясности, мне приходится выполнять это сравнение несколько раз, и я не хочу каждый раз копировать и вставлять этот материал, особенно с длинными именами объектов. С «a» и «b» он выглядит маленьким и простым, но имеет тенденцию к росту... Я хотел бы знать, не упустил ли я для этого какую-то существующую функцию Java.


person Nikolai Prokoschenko    schedule 03.12.2008    source источник


Ответы (9)


Возможно, вы захотите взглянуть на всегда полезный язык Apache Commons, точнее ObjectUtils.equals().

person Guillaume    schedule 03.12.2008

Другой способ сделать

boolean x = null==a ? null==b : a.equals(b);
person Dennis C    schedule 03.12.2008
comment
Мне нравится это - соответствующим образом завернутый в метод - за исключением того, что я ненавижу стиль сравнения константы с переменной, а не наоборот. Конечно, в Java это не нужно. - person tvanfosson; 03.12.2008
comment
Это полезно при сравнении ссылки String с литералом, когда ссылка может быть нулевой, т. е. text.equals(str). В противном случае это просто жеманство. - person Alan Moore; 03.12.2008
comment
По-прежнему актуально, имеет ли a или b логический тип или, начиная с версии 1.5, логический. Я делаю это только для буквальных строк. - person Tom Hawtin - tackline; 03.12.2008
comment
+1. Это идиома, которую я использую (кроме == null, а не null ==). Перетаскивание грязной библиотеки, такой как Apache Commons, для такой тривиальности не является необходимым или желательным. - person erickson; 03.12.2008

Типичный образец:

if (a == b)
{
    return true;
}
if (a == null || b == null)
{
    return false;
}
// Now deal with a and b, knowing that they are non-identical, non-null references

Да, это многословно, но если вы выделите его в отдельный метод, вы сможете держать его под разумным контролем.

person Jon Skeet    schedule 03.12.2008

Что произойдет, если a равно null, а b нет? Я думаю, вы действительно хотите:

boolean x = (a == null && b == null) || (a != null && a.equals(b))

EDIT: вы можете реализовать статический метод NullEquals для класса, который принимает два объекта этого класса и выполняет сравнение, как указано выше, чтобы избежать переписывания и сделать код немного чище.

public class MyClass {

    public static boolean NullEquals( MyClass a, MyClass b )
    {
         return (a == null && b == null) || (a != null && a.equals(b));
    }
}


if (MyClass.NullEquals(a,b))
{
    ...
}
person tvanfosson    schedule 03.12.2008
comment
но если a равно нулю, а b нет, вы также получите нулевой указатель - person Tobias Schulte; 03.12.2008

Не прямой ответ, но если у вас много объектов, которые могут быть нулевыми или нет, это может указывать на некоторые проблемы с вашим кодом. Взгляните на Null Pattern , это альтернативный способ представления отсутствия объекта.

person ljorquera    schedule 03.12.2008

Что о:

boolean x = equals( a, b );

public static boolean equals( Object a, Object b ) {
    if ( a == null && a == b ) {
        return true;
    } else {
        return a == b || a.equals( b );
    }
}

Дайте-ка подумать.

  • если a равно нулю, а a равно b, то все в порядке
  • если a не равно нулю, тогда, если a == b (та же ссылка), верните true по короткому замыканию
  • если a не b (часть 2dns OR, вероятно, b равна null), то верните a (не null). equals(b) независимо от b

Ага покрыто.

person OscarRyz    schedule 04.12.2008

Невозможно добавить комментарий. Считайте это комментарием к ответу Jon Skeet.

Null = Null true или false в Java.

Более конкретно, что должно быть Null = Null, и как и почему другой язык обрабатывает этот случай?

person Biswanath    schedule 03.12.2008
comment
Java рассматривает два нуля как равные, поэтому обычно программа проверки на равенство должна делать то же самое. - person Jon Skeet; 03.12.2008

Самый распространенный способ сделать это:

a==null ? b==null : a.equals(b)

Потенциально немного более эффективные, но менее понятные выражения:

a==b || (a!=null && a.equals(b))

Конечно, вы можете поместить это в метод:

public static boolean eq(Object a, Object b) {
     return a==b || (a!=null && a.equals(b));
}

Обратите внимание на исходный код вопроса NPE, если a равно null, а b не равно null.

person Tom Hawtin - tackline    schedule 03.12.2008

Из соображений производительности обычно рекомендуется проверять личность перед выполнением любой другой логики, как это было сделано в вопросе. Однако многие ответы не учитывают это.

Лучшее место для проверки личности — реализация метода equals в вашем классе:

public boolean equals(Object obj) {
  if(this == obj) return true;
  ...
}

Если это было/можно сделать, вы можете легко провести сравнение:

a == null ? b == null : a.equals(b);

В противном случае вам, возможно, придется проверить личность самостоятельно:

a == null ? b == null : (a == b || a.equals(b));
person ykaganovich    schedule 04.12.2008