Рекомендуется ли использовать оператор xor для логических проверок?

StackOverflow https://stackoverflow.com/questions/160697

Вопрос

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

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

чем

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

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

Мне любопытно узнать о лучших практиках, касающихся использования ^ оператор.

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

Вот такой Вопрос Stackoverflow, связанный с заменой XOR.

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

if (term1 ^ term2) { ...

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

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

ИМХО, этот код можно было бы упростить:

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

Учитывая ясность кода, мое мнение таково, что использование XOR при логических проверках не является типичным использованием побитового оператора XOR.Исходя из моего опыта, побитовый XOR в Java - это обычно используется для реализации маски flag toggle поведение:

flags = flags ^ MASK;

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

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

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

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

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

Лично я предпочитаю выражение "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;
}

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

!= это нормально для сравнения двух переменных.Однако это не работает при множественных сравнениях.

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

по-моему, выглядит лучше, чем

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top