Рекомендуется ли использовать оператор xor для логических проверок?
-
03-07-2019 - |
Вопрос
Лично мне нравится эксклюзивный или, ^
, оператор, когда это имеет смысл в контексте логических проверок из-за его краткости.Я гораздо больше предпочитаю писать
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;
Недавно я использовал 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 необходим.
Мое субъективное личное мнение:Категорически запрещается, для каких бы то ни было целей, использовать равенство (== или !=) для логических значений.Его использование свидетельствует об отсутствии элементарной этики программирования и фундаментальных принципов.Любого, кто бросит на вас растерянный взгляд через ^, следует отправить обратно к основам булевой алгебры (у меня возникло искушение написать здесь "к рекам веры" :) ).