Является ли хорошей практикой использовать оператор XOR (^) в Java для булевых проверок?

Мне лично нравится "эксклюзивный" оператор, когда он имеет смысл в контексте булевых проверок из-за его краткости. Я предпочитаю писать

if (boolean1 ^ boolean2)
{
  //do it
}

чем

if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
  //do it
}

но я часто получаю запутанные взгляды (от других опытных разработчиков Java, а не только от новичков), а иногда и от комментариев о том, как его следует использовать только для побитовых операций. Мне любопытно, как другие практики используют вокруг оператора "^".

Ответ 1

Вместо этого вы можете просто использовать !=.

Ответ 2

Я думаю, что вы ответили на свой собственный вопрос - если вы получаете странные взгляды от людей, вероятно, безопаснее пойти с более явным вариантом.

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

Ответ 3

Я нахожу, что у меня одинаковые разговоры. С одной стороны, у вас есть компактный, эффективный метод достижения вашей цели. С другой стороны, у вас есть то, что остальная часть вашей команды может не понимать, что затрудняет ее поддержку в будущем.

Мое общее правило заключается в том, чтобы спросить, является ли используемая техника тем, что разумно ожидать от программистов в целом. В этом случае я думаю, что разумно ожидать, что программисты будут знать, как использовать логические операторы, поэтому использование xor в инструкции if в порядке.

В качестве примера чего-то, что будет нехорошо, попробуйте использовать xor для замены двух переменных без использования переменной temp. Это трюк, который я бы не ожидал, что все будут знакомы, поэтому он не пройдет обзор кода.

Ответ 4

Я думаю, что было бы хорошо, если бы вы прокомментировали это, например. // ^ == XOR.

Ответ 5

Вы всегда можете просто обернуть его в функцию, чтобы дать ему подробное имя:

public static boolean XOR(boolean A, boolean B) {
    return A ^ B;
}

Но мне кажется, что любому, кто не знал, что для этого оператора Google для Google, очень сложно. Это не будет трудно запомнить после первого раза. Поскольку вы просили другие способы использования, его общее использование XOR для маскировки бит.

Вы также можете использовать XOR для замены значений двумя переменными без использования третьей временной переменной.

// Swap the values in A and B
A ^= B;
B ^= A;
A ^= B;

Вот вопрос fooobar.com/questions/10435/....

Ответ 6

Недавно я использовал xor в проекте JavaScript на работе, а закончил добавление 7 строк комментариев, чтобы объяснить, что происходит. Обоснование использования xor в этом контексте состояло в том, что одно из терминов (term1 в приведенном ниже примере) может принимать не два, а три значения: undefined, true или false, а другое (term2) может быть true или false. Мне пришлось бы добавить дополнительную проверку для случаев undefined, но с xor, было достаточно, так как xor заставляет первый термин сначала оцениваться как логическое, позволяя undefined обрабатываться как false:

    if (term1 ^ term2) { ...

В конце концов, это был немного перебор, но я все равно хотел сохранить его там, как своеобразное пасхальное яйцо.

@Martin: Я думаю, что это хороший пример того, что вы уже заявили:

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

Ответ 7

С учетом ясности кода, мое (субъективное...) мнение заключается в том, что использование XOR в булевых проверках не является типичным использованием для побитового оператора XOR. По моему опыту побитовая XOR в Java обычно используется для реализации поведения маски flag toggle:

flags = flags ^ MASK;

Эта статья Випан Сингла более подробно объясняет пример использования.

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

Ответ 8

if((boolean1 && !boolean2) || (boolean2 && !boolean1)) 
{ 
  //do it 
} 

IMHO этот код можно упростить:

if(boolean1 != boolean2) 
{ 
  //do it 
} 

Ответ 9

Если шаблон использования оправдывает его, почему бы и нет? Хотя ваша команда не сразу распознает оператора, со временем они могут. Люди постоянно изучают новые слова. Почему бы не программировать?

Единственное предостережение, которое я могу сказать, это то, что "^" не имеет семантики короткого замыкания вашей второй логической проверки. Если вам действительно нужна семантика короткого замыкания, то также работает статический метод утилит.

public static boolean xor(boolean a, boolean b) {
    return (a && !b) || (b && !a);
}

Ответ 10

Я лично предпочитаю выражение "boolean1 ^ boolean2" из-за его лаконичности.

Если бы я был в вашей ситуации (работая в команде), я бы поставил бы компромисс, инкапсулируя логику "boolean1 ^ boolean2" в функцию с описательным именем, таким как "isDifferent (boolean1, boolean2)".

Например, вместо использования "boolean1 ^ boolean2" вы бы назвали "isDifferent (boolean1, boolean2)" следующим образом:

if (isDifferent(boolean1, boolean2))
{
  //do it
}

Ваша функция isDifferent (boolean1, boolean2) будет выглядеть так:

private boolean isDifferent(boolean1, boolean2)
{
    return boolean1 ^ boolean2;
}

Конечно, это решение подразумевает использование якобы постороннего вызова функции, который сам по себе подвержен проверке Best Practices, но он избегает подробного (и уродливого) выражения "(boolean1 & &! boolean2) || (boolean2 &! boolean1)"!

Ответ 11

!= в порядке, чтобы сравнить две переменные. Однако он не работает с несколькими сравнениями.

Ответ 12

str.contains("!=") ^ str.startsWith("not(")

выглядит лучше для меня, чем

str.contains("!=") != str.startsWith("not(")

Ответ 13

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

Мое субъективное личное мнение: для любых целей категорически запрещено использовать равенство (== or! =) для булевых. Использование его показывает отсутствие базовой этики и основ программирования. Любой, кто вас путает, должен быть отправлен обратно к основам булевой алгебры (я был соблазн написать "рекам веры" здесь:)).