Операторы 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;
    }
}

С другой стороны, мне кажется, что оригинальный кодер, возможно, играл слишком много кода в гольф, когда он написал это:)

Другие вопросы по тегам