Почему мы обычно используем `||`, а не `|`, в чем разница? - PullRequest
207 голосов
/ 18 августа 2011

Мне просто интересно, почему мы обычно используем логическое ИЛИ || между двумя логическими значениями, а не побитовым ИЛИ |, хотя они оба работают хорошо.*

if(true  | true)  // pass
if(true  | false) // pass
if(false | true)  // pass
if(false | false) // no pass
if(true  || true)  // pass
if(true  || false) // pass
if(false || true)  // pass
if(false || false) // no pass

Можем ли мы использовать | вместо ||?То же самое с & и &&.

Ответы [ 27 ]

3 голосов
/ 19 сентября 2008
| is the binary or operator

|| is the logic or operator
3 голосов
/ 18 августа 2011

Операторы || и && называются условными операторами , тогда как | и & называются побитовыми операторами . Они служат разным целям.

Условные операторы работают только с выражениями, которые статически оцениваются в boolean как с левой, так и с правой стороны.

Битовые операторы работают с любыми числовыми операндами.

Если вы хотите выполнить логическое сравнение, вам следует использовать условные операторы , так как вы добавите в свой код некоторую безопасность типов.

2 голосов
/ 05 сентября 2014

Другие ответы хорошо справились с задачей по рассмотрению функциональных различий между операторами, но ответы могут относиться практически ко всем существующим на сегодняшний день C-производным языкам.Вопрос помечен , и поэтому я постараюсь ответить конкретно и технически за язык Java.

& и | могут быть либо целочисленными побитовыми операторами, либо логическимиЛогические операторы.Синтаксис для побитовых и логических операторов ( §15.22 ):

AndExpression:
  EqualityExpression 
  AndExpression & EqualityExpression

ExclusiveOrExpression:
  AndExpression 
  ExclusiveOrExpression ^ AndExpression

InclusiveOrExpression:
  ExclusiveOrExpression 
  InclusiveOrExpression | ExclusiveOrExpression

Синтаксис для EqualityExpression определен в §15.21 , для которого требуется RelationalExpression определено в §15.20 , что, в свою очередь, требует ShiftExpression и ReferenceType, определенных в §15.19 и §4.3 соответственно.Для ShiftExpression требуется AdditiveExpression, определенное в §15.18 , которое продолжает детализацию, определяя основные арифметические, унарные операторы и т. Д. ReferenceType детализирует все различные способы представления типа.(Хотя ReferenceType не включает в себя примитивные типы, в конечном итоге требуется определение примитивных типов, поскольку они могут быть типом измерения для массива, который равен a ReferenceType.)

Битовые и логические операторы имеют следующие свойства:

  • Эти операторы имеют различный приоритет, & имеет самый высокий приоритет и | самый низкий приоритет.
  • Каждый из этих операторов синтаксически левоассоциативен (каждая группа слева направо).
  • Каждый оператор коммутативен, если выражения операндов не имеют побочных эффектов.
  • Каждый оператор ассоциативен.
  • Битовые и логические операторы могут использоваться для сравнения двух операндов числового типа или двух операндов типа boolean.Все остальные случаи приводят к ошибке времени компиляции.

Различие между тем, является ли оператор побитовым или логическим, зависит от того, являются ли операнды «конвертируемыми впримитивный целочисленный тип "( §4.2 ) или, если они имеют типы boolean или Boolean ( §5.1.8 ).

Если операндыявляются целочисленными типами, двоичное числовое продвижение ( §5.6.2 ) выполняется для обоих операндов, оставляя их обоих либо long с, либо int с для операции.Тип операции будет типом (повышенных) операндов.В этот момент & будет побитовым И, ^ будет побитовым исключающим ИЛИ, а | будет побитовым ИЛИ.( §15.22.1 )

Если операндами являются boolean или Boolean, операнды при необходимости будут преобразованы в распаковку ( §5.1.8 ), а тип операции будет boolean.& приведет к true, если оба операнда true, ^ приведет к true, если оба операнда различны, и | приведет к true, если любой из операндов true.( §15.22.2 )

Напротив, && - это «оператор условных операторов» ( §15.23 ) и || является «оператором условного или» ( §15.24 ).Их синтаксис определен следующим образом:

ConditionalAndExpression:
  InclusiveOrExpression 
  ConditionalAndExpression && InclusiveOrExpression

ConditionalOrExpression:
  ConditionalAndExpression 
  ConditionalOrExpression || ConditionalAndExpression

&& похож на &, за исключением того, что он оценивает правый операнд, только если левый операнд равен true.|| похож на |, за исключением того, что он оценивает правый операнд, только если левый операнд равен false.

Условно-И имеет следующие свойства:

  • Условный оператор and синтаксически левоассоциативен (он группируется слева направо).
  • Условный оператор and полностью ассоциативен в отношении как побочных эффектов, так и значения результата.То есть для любых выражений a, b и c вычисление выражения ((a) && (b)) && (c) дает тот же результат с теми же побочными эффектами, возникающими в том же порядке, что и вычисление выражения (a) && ((b) && (c)).
  • Каждый операнд оператора условного оператора and должен иметь тип boolean или Boolean, иначе произойдет ошибка времени компиляции.
  • Типpe выражения условного оператора and всегда равно boolean.
  • Во время выполнения выражение левого операнда вычисляется первым;если результат имеет тип Boolean, он подвергается распаковке преобразования ( §5.1.8 ).
  • Если результирующее значение равно false, значение условного-ивыражение - false, а выражение правого операнда не вычисляется.
  • Если значение левого операнда равно true, то вычисляется правое выражение;если результат имеет тип Boolean, он подвергается распаковке без преобразования ( §5.1.8 ).Результирующее значение становится значением условного выражения и выражения.
  • Таким образом, && вычисляет тот же результат, что и & для boolean операндов.Он отличается только тем, что выражение правого операнда вычисляется условно, а не всегда.

Условно-Или имеет следующие свойства:

  • Условный оператор или синтаксически является левоассоциативным (он группируется слева направо).
  • Условный оператор или полностью ассоциативен в отношении как побочных эффектов, так и значения результата.То есть для любых выражений a, b и c оценка выражения ((a) || (b)) || (c) дает тот же результат с теми же побочными эффектами, возникающими в том же порядке, что и оценка выражения (a) || ((b) || (c)).
  • Каждый операнд условного оператора или должен иметь тип boolean или Boolean, иначе возникает ошибка времени компиляции.
  • Типусловное выражение или всегда равно boolean.
  • Во время выполнения выражение левого операнда вычисляется первым;если результат имеет тип Boolean, он подвергается распаковке преобразования ( §5.1.8 ).
  • Если результирующее значение равно true, значение условного иливыражение - true, а выражение правого операнда не вычисляется.
  • Если значение левого операнда равно false, то вычисляется правое выражение;если результат имеет тип Boolean, он подвергается распаковке ( §5.1.8 ).Результирующее значение становится значением условного выражения или.
  • Таким образом, || вычисляет тот же результат, что и | для boolean или Boolean операндов.Он отличается только тем, что выражение правого операнда оценивается условно, а не всегда.

Вкратце, как @JohnMeagher неоднократно указывал в комментариях, & и | фактически являются логическими операторами без короткого замыкания в конкретном случае, когда операнды либо boolean, либо Boolean.С хорошими практиками (то есть: никакие вторичные эффекты), это незначительная разница.Однако когда операнды не boolean с или Boolean с, операторы ведут себя очень по-разному: побитовые и логические операции просто не очень хорошо сравниваются на высоком уровне программирования Java.

2 голосов
/ 19 августа 2013

1). (Выражение1 | выражение2), |Оператор оценивает выражение2 независимо от того, является ли результат выражения 1 истинным или ложным.

Пример:

class Or 
{
    public static void main(String[] args) 
    {
        boolean b=true;

        if (b | test());
    }

    static boolean test()
    {
        System.out.println("No short circuit!");
        return false;
    }
}

2).|оператор не будет вычислять expression2, если выражение1 истинно.

Пример:

class Or 
{
    public static void main(String[] args) 
    {
        boolean b=true;

        if (b || test())
        {
            System.out.println("short circuit!");
        }
    }

    static boolean test()
    {
        System.out.println("No short circuit!");
        return false;
    }
}
2 голосов
/ 24 августа 2010

Примечание: у Java есть | =, но нет || =

Пример того, когда вы должны использовать ||это когда первое выражение является тестом, чтобы увидеть, взорвется ли второе выражение.Например, используя один |в следующем случае может привести к NPE.

public static boolean isNotSet(String text) {
   return text == null || text.length() == 0;
}
1 голос
/ 13 июля 2018

Когда у меня возник этот вопрос, я создал тестовый код, чтобы получить представление об этом.

public class HelloWorld{

   public static boolean bool(){
      System.out.println("Bool");
      return true;
   }

   public static void main(String []args){

     boolean a = true;
     boolean b = false;

     if(a||bool())
     {
        System.out.println("If condition executed"); 
     }
     else{
         System.out.println("Else condition executed");
     }

 }
}

В этом случае мы меняем только левую сторону, если условие добавляет a или b.

|| Сценарий, когда левая сторона истинна [if (a || bool ())]

вывод "If condition executed"

|| Сценарий, когда левая сторона неверна [if (b || bool ())]

Выход-

Bool
If condition executed

Conclusion of || При использовании || правая сторона проверяет, только если левая сторона ложна. | Сценарий, когда левая сторона истинна [if (a | bool ())]

Выход-

Bool
If condition executed

| Сценарий, когда левая сторона ложна [if (b | bool ())]

Выход-

Bool
If condition executed

Conclusion of | При использовании | проверьте левую и правую сторону.

1 голос
/ 10 апреля 2016

Основная разница между ними заключается в том, что |сначала преобразует значения в двоичные, затем выполняет битовую обработку или операцию.Между тем, ||не преобразует данные в двоичный файл и просто выполняет выражение или в исходном состоянии.

int two = -2; int four = -4;
result = two | four; // bitwise OR example

System.out.println(Integer.toBinaryString(two));
System.out.println(Integer.toBinaryString(four));
System.out.println(Integer.toBinaryString(result));

Output:
11111111111111111111111111111110
11111111111111111111111111111100
11111111111111111111111111111110

Подробнее: http://javarevisited.blogspot.com/2015/01/difference-between-bitwsie-and-logical.html#ixzz45PCxdQhk

1 голос
/ 15 сентября 2013

Не короткое замыкание может быть полезным.Иногда вы хотите убедиться, что два выражения оценивают.Например, скажем, у вас есть метод, который удаляет объект из двух отдельных списков.Возможно, вы захотите сделать что-то вроде этого:

class foo {

    ArrayList<Bar> list1 = new ArrayList<Bar>();
    ArrayList<Bar> list2 = new ArrayList<Bar>();

    //Returns true if bar is removed from both lists, otherwise false.
    boolean removeBar(Bar bar) {
        return (list1.remove(bar) & list2.remove(bar));
    }
}

Если ваш метод вместо этого использует условный операнд, он не сможет удалить объект из второго списка, если первый список вернул false.

//Fails to execute the second remove if the first returns false.
boolean removeBar(Bar bar) {
    return (list1.remove(bar) && list2.remove(bar));
}

Это не удивительно полезно, и (как и в большинстве задач программирования) вы можете достичь этого другими способами.Но это случай использования побитовых операндов.

1 голос
/ 18 августа 2011

Одно главное отличие состоит в том, что || и && демонстрируют «короткое замыкание», поэтому RHS будет оцениваться только при необходимости.

Например,

if (a || b) {
    path1...
} else {
    path2..
}

Выше, если a равно true, b не будет проверяться, и path1 выполняется. Если | Тогда обе стороны будут оцениваться, даже если «а» истинно.

См. Здесь и здесь , для получения дополнительной информации.

Надеюсь, это поможет.

1 голос
/ 19 сентября 2008

||возвращает логическое значение, используя ИЛИ два значения (поэтому его называют ЛОГИЧЕСКИМ илиесли они оба ложные.

|является оператором, который выполняет побитовую операцию над двумя значениями.Чтобы лучше понять побитовые операции, вы можете прочитать здесь:

http://en.wikipedia.org/wiki/Bitwise_operation

...