Почему мы обычно используем `||` not `|`, в чем разница?

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

Я имею в виду, посмотрите на следующее:

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

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

Ответ 1

Если вы используете формы || и &&, а не формы | и & этих операторов, Java не будет пытаться оценить только правый операнд.

Это вопрос, хотите ли вы провести короткую замыкание оценки или нет - большую часть времени вы хотите.

Хорошим способом проиллюстрировать преимущества короткого замыкания было бы рассмотреть следующий пример.

Boolean b = true;
if(b || foo.timeConsumingCall())
{
   //we entered without calling timeConsumingCall()
}

Еще одно преимущество, как упоминал Джереми и Питер, для короткого замыкания - это нулевая контрольная проверка:

if(string != null && string.isEmpty())
{
    //we check for string being null before calling isEmpty()
}

подробнее

Ответ 2

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

Кроме того, | может использоваться для выполнения операции побитового ИЛИ со значениями байтов/коротких/целых/длинных. || не могу.

Ответ 3

Итак, просто для того, чтобы основываться на других ответах с примером, короткое замыкание имеет решающее значение в следующих защитных проверках:

if (foo == null || foo.isClosed()) {
    return;
}

if (bar != null && bar.isBlue()) {
    foo.doSomething();
}

Использование | и & вместо этого может привести к появлению NullPointerException.

Ответ 4

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

Например:

int i = 12;
if (i == 10 & i < 9) // It will check if i == 10 and if i < 9
...

Перепишите это:

int i = 12;
if (i == 10 && i < 9) // It will check if i == 10 and stop checking afterward because i != 10
...

Другой пример:

int i = 12;
if (i == 12 | i > 10) // It will check if i == 12 and it will check if i > 10
...

Перепишите это:

int i = 12;
if (i == 12 || i > 10) // It will check if i == 12, it does, so it stops checking and executes what is in the if statement
...

Ответ 5

Также обратите внимание на общую ошибку: у ленивых операторов есть приоритет над ленивыми, поэтому:

boolean a, b, c;
a || b && c; //resolves to a || (b && c)
a | b && c; //resolves to (a | b) && c

Будьте осторожны при их смешивании.

Ответ 6

В дополнение к короткому замыканию, еще одна вещь, о которой следует помнить, заключается в том, что выполнение побитовой логической операции над значениями, которые могут быть отличными от 0 или 1, имеет совсем другое значение, чем условная логика. Хотя это ИСПОЛЬЗОВАНИЕ одинаково для | и ||, при & и && вы получаете очень разные результаты (например, 2 & 4 равно 0/false, а 2 && 4 равно 1/true).

Если вещь, которую вы получаете от функции, на самом деле является кодом ошибки, и вы тестируете не-0-ness, это может иметь большое значение.

Это не такая уж большая проблема в Java, где вам нужно явно указывать тип для boolean или сравнивать с 0 или тому подобное, но на других языках с похожим синтаксисом (C/С++ и др.) это может быть довольно запутанным.

Также обратите внимание, что и и | может применяться только к значениям целочисленного типа, а не ко всему, что может быть эквивалентно логическому тесту. Опять же, на языках, отличных от Java, существует немало вещей, которые можно использовать в качестве логического с неявным сравнением != 0 (указатели, float, объекты с operator bool() и т.д.) И побитовые операторы почти всегда бессмысленны в этих контекстах.

Ответ 7

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

Однако это микро-оптимизация, которая редко имеет значение, за исключением кода самого низкого уровня.

Ответ 8

|| является логическим или оператором, а | является поразрядным или оператором.

boolean a = true;
boolean b = false;

if (a || b) {
}

int a = 0x0001;
a = a | 0x0002;

Ответ 9

a | b: оценить b в любом случае

a || b: оценить b , только если a оценивает значение false

Ответ 10

В дополнение к тому, что | является побитовым оператором: || является оператором короткого замыкания - когда один элемент является ложным, он не будет проверять другие.

 if(something || someotherthing)
 if(something | someotherthing)

если что-то ИСТИНА, || не будет оценивать someotherthing, в то время как | Сделаю. Если переменные в ваших if-statement являются фактически вызовами функции, используя || возможно, сэкономит много времени.

Ответ 11

Java || и && операторы оценивают только правую часть булевского выражения, если им нужно. Это называется ленивой оценкой.

Эквивалентный код для || оператор

// Simulate 

// if(b||c)
//   doThis();
// else
//   doThat();
if(b)
  doThis();
else
  if(c)
    doThis();
else
    doThat();

// Similar for &&

Это требует намного меньше времени для оценки определенных выражений. Однако иногда вы можете использовать | Оператор:

public boolean updateGlobal(){
  global = 2;
  return true;
}

if(false | updateGlobal()){
  foo();
}

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

Ответ 12

| is the binary or operator

|| is the logic or operator

Ответ 13

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

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

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

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

Ответ 14

Замечание: Java имеет | =, но не || =

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

public static boolean isNotSet(String text) {
   return text == null || text.length() == 0;
}

Ответ 15

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). (выражение1 || выражение2), || оператор не будет оценивать выражение2, если выражение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;
    }
}

Ответ 16

Другие ответы хорошо отражают функциональную разницу между операторами, но ответы могут быть применены практически к каждому существующему 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 не содержит примитивные типы, в конечном итоге требуется определение примитивных типов, поскольку они могут быть типом измерения для массива, который является ReferenceType.)

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

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

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

Если операнды являются целыми типами, двоичная цифровая продвижка (§5.6.2) выполняется на обоих операндах, оставляя их как в качестве long или int для операции. Тип операции будет типом (продвинутых) операндов. В этот момент & будет побитовым И, ^ будет побитовым исключением OR, а | будет побитовым включением ИЛИ. (§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.

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

  • Условный и оператор синтаксически лево-ассоциативный (он группирует слева направо).
  • Условный оператор и оператор полностью ассоциативен как по отношению к обеим побочным эффектам, так и по результату. То есть для любых выражений a, b и c оценка выражения ((a) && (b)) && (c) дает тот же результат с теми же побочными эффектами, происходящими в том же порядке, что и оценка выражения (a) && ((b) && (c)).
  • Каждый операнд условного оператора и оператора должен иметь тип boolean или boolean, или возникает ошибка времени компиляции.
  • Тип условного выражения и выражения всегда 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 s, операторы ведут себя очень по-разному: побитовые и логические операции просто не сравниваются хорошо на высоком уровне программирования Java.

Ответ 17

|| возвращает логическое значение посредством OR'ing двух значений (Thats, почему его называют ЛОГИЧЕСКИМ или)

IE:

if (A || B) 

Вернет true, если либо A, либо B истинно, либо false, если они оба являются ложными.

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

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

Ответ 18

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

Например,

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

Выше, если a истинно, тогда b не будет проверен, а путь1 будет выполнен. Если | был использован, тогда обе стороны будут оцениваться, даже если "а" истинно.

Смотрите здесь и здесь, для немного больше информация.

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

Ответ 19

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

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));
}

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

Ответ 20

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

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

Ответ 21

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

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())]

output "If condition executed"

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

Output-

Bool
If condition executed

Conclusion of || При использовании || , правая сторона проверяет только, когда левая сторона ложна.

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

Output-

Bool
If condition executed

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

Output-

Bool
If condition executed

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

Ответ 22

| = побитовое или, || = логика или

Ответ 23

Обычно я использую, когда есть оператор pre increment и post increment. Посмотрите на следующий код:

package ocjpPractice;
/**
 * @author tithik
 *
 */
public class Ex1 {

    public static void main(String[] args) {
    int i=10;
    int j=9;
    int x=10;
    int y=9;
    if(i==10 | ++i>j){
        System.out.println("it will print in first if");  
        System.out.println("i is: "+i);
    }

    if(x==10 ||++x>y){
        System.out.println("it will print in second if");   
        System.out.println("x is: "+x);
    }
    }
}

выход:

он будет печататься первым, если
Я: 11

он будет печатать во втором, если
x: 10

оба блока if одинаковы, но результат отличается. когда есть |, оба условия будут оценены. Но если это ||, он не будет оценивать второе условие, поскольку первое условие уже истинно.

Ответ 24

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

Например, если вы хотите проверить проверку формы и хотите показать пользователю все недопустимые поля с текстом ошибок, а не только первое недопустимое поле.

Оператор

|| был бы,

   if(checkIfEmpty(nameField) || checkIfEmpty(phoneField) || checkIfEmpty(emailField)) {
      // invalid form with one or more empty fields
   }

   private boolean checkIfEmpty(Widget field) {
      if(field.isEmpty()) {
        field.setErrorMessage("Should not be empty!");
        return true;
      }
      return false;
   }

Итак, с приведенным выше фрагментом, если пользователь отправляет форму со всеми пустыми полями, ТОЛЬКО nameField будет отображаться с сообщением об ошибке. Но, если вы измените его на,

   if(checkIfEmpty(nameField) | checkIfEmpty(phoneField) | checkIfEmpty(emailField)) {
      // invalid form with one or more empty fields
   }

Он покажет правильное сообщение об ошибке в каждом поле, независимо от условий true.

Ответ 25

После внимательного прочтения этой темы мне все еще неясно, соответствует ли использование | в качестве логического оператора правилам шаблонов Java.

Я недавно изменил код в запросе на получение ответа, в котором комментарий

if(function1() | function2()){
  ...
}

пришлось изменить на

boolean isChanged = function1();
isChanged |= function2();
if (isChanged){
  ...
}

Какая фактически принятая версия?

В документации Java нет упоминания | как логического оператора ИЛИ без короткого замыкания.

Не заинтересованы в голосовании, но больше в выяснении стандарта?! Обе версии кода компилируются и работают как положено.

Ответ 26

|| является логическим или и | бит-бит или.

Ответ 27

Операторы Java

| побитовое, или || является логическим или.

Ответ 29

| является побитовым оператором. || является логическим оператором.

Один принимает два бита и/или их.

Определяется истина (это ИЛИ). Если это верно или это правда, тогда ответ верен.

О, и люди-данги быстро отвечают на эти вопросы.