Операторы Java: |= побитовое ИЛИ и пример присваивания
Я просто иду через код, который кто-то написал, и я увидел |=
Использование, глядя на операторы Java, предлагает побитовое или или и присвоить операцию, кто-нибудь может объяснить и привести мне пример этого?
Вот код, который читает это:
for (String search : textSearch.getValue())
matches |= field.contains(search);
6 ответов
a |= b;
такой же как
a = (a | b);
Он вычисляет побитовое ИЛИ двух операндов и присваивает результат левому операнду.
Чтобы объяснить ваш пример кода:
for (String search : textSearch.getValue())
matches |= field.contains(search);
я предполагаю matches
это boolean
; это означает, что побитовые операторы ведут себя так же, как логические операторы.
На каждой итерации цикла OR
текущее значение matches
с тем, что возвращается из field.contains()
, Это имеет эффект установки его на true
если это уже было правдой, или если field.contains()
возвращает истину.
Таким образом, он рассчитывает, если какой-либо из вызовов field.contains()
на протяжении всего цикла вернулся true
,
a |= b
такой же как a = (a | b)
Булевы переменные
В boolean
контекст, это означает:
if (b) {
a = true;
}
то есть если b
тогда верно a
будет правдой, иначе a
будет неизменным.
Побитовые операции
В некотором смысле это означает, что каждый двоичный бит, установленный в b
станет установленным в a
, Биты, которые ясно в b
будет неизменен в a
,
Так что, если бит 0 установлен в b
также станет установленным в a
согласно приведенному ниже примеру:
Это установит нижний бит целого числа:
a |= 0x01
Это очистит нижний бит:
a &= ~0x01
Это переключит нижний бит:
a ^= 0x01;
Этот код:
int i = 5;
i |= 10;
эквивалентно этому коду:
int i = 5;
i = i | 10;
Точно так же этот код:
boolean b = false;
b |= true;
эквивалентно этому:
boolean b = false;
b = b | true;
В первом примере выполняется побитовое ИЛИ. Во втором примере выполняется логическое ИЛИ.
a |= b
такой же как a = a | b
a | b
является побитовым оператором, если оба операнда являются целочисленными типами (int, short и т. д.). Если оба операнда являются булевыми, то это булевы или.
Когда оба a
а также b
являются логическими, разница между a | b
а также a || b
является то, что в первом всегда оцениваются обе стороны, в последнем b
оценивается только если a
ложно Это своего рода "быстрый" оператор.
Это полезно для таких ситуаций:
if (a == null || a.equals(b)) { .. do something .. } // works
if (a == null | a.equals(b)) { .. do something .. } // NPE if a is null
С другой стороны, ||
фактически реализован как еще один условный переход в байт-коде / машинном коде. В некоторых случаях может быть быстрее оценить булевы условия, используя |
оператор, чтобы избежать дополнительного прыжка (и, следовательно, ветвление, и т. д...). Определенно что-то для микро-бенчмаркинга низкого уровня, чтобы выяснить, что лучше (и, как правило, не важно в большинстве приложений).
Когда вы делаете a |= b
вы всегда оцениваете оба a
а также b
, Это не имеет смысла иметь a ||= b
операторы, так как эквивалент a = a || b
будет переводить на:
if (a) a = true;
else if (b) a = true
else a = false;
... из-за условного характера ||
оценка. Другими словами, b
не будет оцениваться, если a
уже было правдой.
Возможно ли, что в коде есть ошибка, и это подразумевалось
matches = matches || field.contains(search);
так что совпадения должны быть true
если хотя бы одно поле содержит search
переменная?
Этот фрагмент кода является плохим примером того, когда использовать этот оператор. Честно говоря, я не могу придумать отличный пример того, когда использовать этот оператор, но вот моя лучшая попытка:
boolean somethingIsTrue = testSomethingTrue();
if(somethingIsTrue){
//Do something
}
somethingIsTrue |= testSomethingElseTrue();
if(somethingIsTrue){
//Do something else
}
somethingIsTrue |= testSomethingElseTrue2();
if(somethingIsTrue){
//Do something else than something or something else
}
Примечание: вам нужно 3, если в противном случае вы могли бы просто сделать somethingIsTrue | testSomethingElseTrue()
для второго, если.
Если вам интересно, почему вы не должны использовать оператор в первом примере, вот почему:
С точки зрения производительности, он плохой, потому что он выполняет сравнение и присваивание для каждого цикла вместо простого сравнения. Кроме того, он продолжает итерацию, даже если будущие итерации не будут иметь эффекта (один раз matches
устанавливается на true
это не изменится, и String.contains
не имеет побочных эффектов).
Это также плохо с точки зрения читабельности, основанной исключительно на существовании этого вопроса;)
Таким образом, вместо этого фрагмента я бы выбрал:
for (String search : textSearch.getValue()){
if(field.contains(search)){
matches = true;
break;
}
}
С другой стороны, мне кажется, что оригинальный кодер, возможно, играл слишком много кода в гольф, когда он написал это:)