Подтвердить что ты не робот

Причина существования некоротких логических операторов

При использовании операндов boolean & и | становятся логическими операторами в Раздел 15.22.2 JLS. В отличие от && и ||, однако, они не замыкаются; они всегда оценивают обе стороны. У меня есть глупый вопрос: почему все еще существуют менее эффективные логические операторы без коротких замыканий (&, |), когда мы имеем более эффективные логические операторы короткого замыкания (&&, ||)? Я имею в виду, каково реальное использование логических операторов без коротких замыканий, в отличие от логических операторов короткого замыкания? Другими словами, каково использование всегда оценки обеих сторон с помощью некоротких логических операторов?

4b9b3361

Ответ 1

Обновленный ответ:

Извиняюсь, я пропустил слово "логично" в вашем вопросе, хотя он есть. (Я позволил немного подчеркнуть это с помощью редактирования.)

Рассмотрим случай, когда вы хотите, чтобы любые побочные эффекты всегда возникали, независимо от того, оценивает ли левое выражение true или false. Например, контраст:

if (foo() & bar()) {
    // Only call this if both operations returned true
}

с

if (foo() && bar()) {
    // Only call this if both operations returned true
}

Предположим, что оба foo и bar имеют эффекты, которые мы хотим выполнить независимо от того, возвращается ли foo true или false. В первом выше, я знаю, что bar всегда будет вызван и будет иметь эффект. В последнем, конечно, bar может или не может быть вызван. Если бы у нас не было версии с коротким замыканием, нам пришлось бы использовать временные переменные:

boolean fooResult, barResult;
fooResult = foo();
barResult = bar();
if (fooResult && barResult) {
    // ...
}

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

Оригинальный ответ:

Как вы предлагаете & (или |) короткозамкнутый оператор? С && и || это имеет смысл, потому что вы имеете дело с булевыми условиями: они могут быть истинными или ложными, нет оттенков серого. Но & и | имеют дело с битами, а не с булевыми. Результатом является число. Я имею в виду, я полагаю, что & не мог оценить правую часть, если левая сторона была 0, и аналогично | не могла ее оценить, если левая сторона была все-бит-на-за тип был, но я не вижу большого смысла, чтобы сделать один крайный случай каждого оператора значительным (по сравнению с 254 или более другими случаями).

Ответ 2

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

while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {

    // re-prompt

}

Если второе условие не было оценено из-за короткого замыкания, attempts никогда не будет увеличиваться. Таким образом, обеспечивается более высокая гибкость программиста.

Ответ 3

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

Не могу вспомнить хороший пример, но помните, что мне иногда нужны операторы "короткого замыкания".

Hmmm.... Ниже приведен пример WRONG, который не будет работать без "короткого замыкания" ИЛИ:

if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) {

    // do something which requires bot object1 and object2 assigned

}

Ответ 4

Мой случай (С++):

void setFields(Parameters bundle)
{
  if (setIfDifferent(&field1, bundle.value1) | 
      setIfDifferent(&field2, bundle.value2) |
      setIfDifferent(&field3, bundle.value3)) {
    storeState();
  }
}

setIfDifferent() устанавливает поле объекта с новым значением, если они отличаются, и в этом случае он возвращает true; или он возвращает false, если поле и новое значение совпадают. Итак, мы хотим попытаться установить все поля, и если какой-либо из них изменился, то мы хотим сохранить новое состояние объекта.

Ответ 5

В моем случае у меня есть два метода, которые сравнивают два разных, но связанных объекта (Object2 - это атрибут Object1), чтобы увидеть, были ли какие-либо изменения. Обновление должно быть выполнено, если либо обновлены, но оба должны быть оценены так, чтобы объекты были изменены, если они были изменены. Поэтому требуется однопроходное сравнение "ИЛИ".

Пример:

if (compare(object1, currentObject1) | comparison(object2, currentObject2)) {
    updateObject1(object1);
}

Ответ 6

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

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

Скажи:

if(a = (checkForSomeCondition()) | b = checkForAnotherCondition())
{
 //now do something here with a and b that has been cached
}

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

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