Java-операторы: | = побитовое ИЛИ и назначить пример [дубликат]

17

Я просто просматриваю код, который написал кто-то, и я видел |= использования, глядя на Java-операторы, он предлагает побитовое или назначить операцию, может ли кто-нибудь объяснить и дать мне пример?

Вот код, который его читал:

    for (String search : textSearch.getValue())
         matches |= field.contains(search);
    
задан Rachel 13.04.2012 в 15:47
источник
  • Не могли бы вы показать нам код, который вы прочитали? –  talnicolas 13.04.2012 в 15:49
  • @talnicolas: обновленный вопрос с кодом. –  Rachel 13.04.2012 в 15:50
  • Каков тип совпадений? int или boolean? –  adranale 13.04.2012 в 15:51
  • соответствует логическому –  Rachel 13.04.2012 в 15:52
  • см. мой ответ, вероятно, поразрядный или вообще не подразумевается здесь! –  adranale 13.04.2012 в 15:56

6 ответов

24
a |= b;

совпадает с

a = (a | b);

Он вычисляет побитовый OR двух операндов, а присваивает результат левому операнду.

Чтобы объяснить ваш пример кода:

for (String search : textSearch.getValue())
    matches |= field.contains(search);

Я предполагаю, что matches является boolean ; это означает, что побитовые операторы ведут себя так же, как логические операторы.

На каждой итерации цикла оно OR s текущее значение matches с тем, что возвращается из field.contains() . Это влияет на значение true , если оно уже было true, или , если field.contains() возвращает true.

Итак, он вычисляет, если любой вызовов field.contains() , на протяжении всего цикла, возвращается true .

    
ответ дан Graham Borland 13.04.2012 в 15:50
источник
  • можете ли вы ввести некоторые значения для a и b? –  Rachel 13.04.2012 в 15:51
  • oh ok, теперь это имеет смысл –  Rachel 13.04.2012 в 15:57
  • "это означает, что побитовые операторы ведут себя так же, как логические операторы". На самом деле логические операторы будут замыкаться. Возможно, здесь требуется короткое замыкание. –  smp7d 13.04.2012 в 16:13
  • Следует также отметить, что если contains () не имеет побочных эффектов, это довольно неэффективно. Добавление, по крайней мере, if (соответствует) {break; } внутри цикла было бы намного приятнее ... (Хотя я полагаю, что getValue () может возвращать так мало поисков, что это не будет иметь заметной разницы ...) –  Izkata 13.04.2012 в 20:03
10

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;

ответ дан Alnitak 13.04.2012 в 15:49
источник
  • может вводить некоторые значения числа a и объяснять детали. –  Rachel 13.04.2012 в 15:52
3

Этот код:

int i = 5;
i |= 10;

эквивалентен этому коду:

int i = 5;
i = i | 10;

Аналогично, этот код:

boolean b = false;
b |= true;

эквивалентно этому:

boolean b = false;
b = b | true;

В первом примере выполняется бит-бит ИЛИ. Во втором примере выполняется логическое ИЛИ.

    
ответ дан Óscar López 13.04.2012 в 15:50
источник
1

Возможно ли, что код имеет ошибку, и это означало

matches = matches || field.contains(search);

, так что совпадения должны быть true , если хотя бы одно поле содержит переменную search ?

    
ответ дан adranale 13.04.2012 в 15:55
источник
  • ваш код не является функционально одинаковым - если совпадения уже верны, тогда оператор короткого замыкания будет препятствовать оценке field.contains (search). AFAIK оператор | = это не сделает. –  Alnitak 13.04.2012 в 16:05
  • Это означает, что мой код - это оптимизация исходного кода –  adranale 13.04.2012 в 16:06
  • , только если это действительно так, что .contains () не вызывается в этих обстоятельствах. –  Alnitak 13.04.2012 в 16:07
  • вы имеете в виду, если метод .contains () не имеет побочных эффектов –  adranale 13.04.2012 в 16:14
  • да, в основном - в этом случае это, вероятно, не имеет значения, но стоит знать, что для булевых переменных a | = func () совпадает с a = a | func (), который не является функционально таким же, как a = a || func (), хотя конечный результат на a один и тот же. –  Alnitak 13.04.2012 в 18:26
1

a |= b совпадает с a = a | b

a | b - побитовый оператор, если оба операнда являются целыми типами (int, short и т. д.). Если оба операнда являются логическими, то он является логическим или.

Когда оба a и b являются логическими, разница между a | b и a || b заключается в том, что в первом, обе стороны оцениваются always , в последнем 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 уже было истинным.

    
ответ дан ɲeuroburɳ 13.04.2012 в 16:20
источник
0

Этот фрагмент кода является плохим примером того, когда использовать этот оператор. Честно говоря, я не могу придумать отличный пример того, когда использовать этот оператор, но вот моя лучшая попытка:

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 ifs, потому что иначе вы могли бы просто сделать somethingIsTrue | testSomethingElseTrue() для второго, если.

Если вам интересно, почему вы не должны использовать оператор в первом примере, вот почему:

С точки зрения производительности это плохо, потому что он выполняет сравнение и присваивание для каждого цикла вместо простого сравнения. Кроме того, он продолжает итерацию, даже если будущие итерации не будут иметь эффекта (когда matches будет установлено в true , он не изменится, а String.contains не будет иметь побочных эффектов).

Он также плохой с точки зрения удобочитаемости, основанный исключительно на существовании этого вопроса;)

Таким образом, вместо этого фрагмента я бы пошел:

for (String search : textSearch.getValue()){
    if(field.contains(search)){
        matches = true;
        break;
    }
}

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

    
ответ дан Briguy37 13.04.2012 в 18:36
источник