Рекомендуется ли использовать оператор xor для булевых проверок?
мне лично нравится эксклюзивный или, ^
, оператор, когда это имеет смысл в контексте булевых проверок из-за его краткости. Я предпочитаю писать
if (boolean1 ^ boolean2)
{
//do it
}
чем
if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
//do it
}
но я часто путаю взгляды других опытных разработчиков Java (а не только новичков), а иногда и комментарии о том, как его следует использовать только для побитовых операций.
мне любопытно узнать о лучших практиках в отношении использования the ^
оператора.
13 ответов
Я думаю, вы ответили на свой вопрос - если вы получаете странные взгляды от людей, вероятно, безопаснее пойти с более явным вариантом.
Если вам нужно прокомментировать его, то вам, вероятно, лучше заменить его более подробной версией и не заставлять людей задавать вопрос в первую очередь.
Я нахожу, что у меня много подобных разговоров. С одной стороны, у вас есть компактный, эффективный способ достижения вашей цели. С другой стороны, у вас есть то, что остальная часть вашей команды может не понять, что затрудняет ее поддержание в будущем.
мое общее правило-спросить, является ли используемая техника чем-то, что разумно ожидать от программистов в целом. В этом случае я думаю, что разумно ожидать, что программисты знают, как используйте логические операторы, поэтому использование xor в операторе if нормально.
в качестве примера чего-то, что было бы не в порядке, возьмите трюк использования xor для замены двух переменных без использования временной переменной. Это трюк, с которым я бы не ожидал, что все будут знакомы, поэтому он не пройдет проверку кода.
вы всегда можете просто оберните его в функцию, чтобы дать ему подробное название:
public static boolean XOR(boolean A, boolean B) {
return A ^ B;
}
но мне кажется, что для тех, кто не знал, что такое оператор^, было бы нетрудно Google это очень быстро. Это не будет трудно вспомнить после первого раза. Так как вы попросили других применений, его общим для использования 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) { ...
имея в виду ясность кода, я считаю, что использование XOR в булевых проверках не является типичным использованием для побитового оператора XOR. По моему опыту, побитовый XOR в Java-это обычно используется для реализации маски flag toggle
поведение:
flags = flags ^ MASK;
этой статья Vipan Singla объясняет случай использования более подробно.
Если вам нужно использовать побитовый XOR, как в вашем примере, прокомментируйте, почему вы его используете, так как он, вероятно, потребует даже побитового грамотная аудитория остановится на своем пути, чтобы понять, почему вы ее используете.
if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
//do it
}
IMHO этот код может быть упрощен:
if(boolean1 != boolean2)
{
//do it
}
если шаблон использования оправдывает это, почему бы и нет? В то время как ваша команда не распознает оператора сразу, со временем они могли бы. Люди все время учат новые слова. Почему не в программировании?
единственное предупреждение, которое я могу заявить, - это то, что " ^ " не имеет семантики короткого замыкания вашей второй булевой проверки. Если вам действительно нужна семантика короткого замыкания, то работает и статический метод 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 является обязательным.
мое субъективное личное мнение: абсолютно запрещено, для каких-либо целей, использовать равенство (== или != ) для логических значений. Использование его показывает отсутствие базовой этики программирования и основ. Любой, кто дает вам смущенные взгляды, должен быть отправлен обратно к основам булевой алгебры (у меня было искушение написать " к рекам веры" здесь :) ).