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