Коротке замикання логічного оператора Java


100

Яка множина коротке замикання, і що саме означає, що складний умовний вираз коротке замикання?

public static void main(String[] args) {
  int x, y, z;

  x = 10;
  y = 20;
  z = 30;

  // T T
  // T F
  // F T
  // F F

  //SET A
  boolean a = (x < z) && (x == x);
  boolean b = (x < z) && (x == z);
  boolean c = (x == z) && (x < z);
  boolean d = (x == z) && (x > z);
  //SET B    
  boolean aa = (x < z) & (x == x);
  boolean bb = (x < z) & (x == z);
  boolean cc = (x == z) & (x < z);
  boolean dd = (x == z) & (x > z);

}

4
Дивіться це питання: stackoverflow.com/questions/7101992 / ...
Eng.Fouad

Відповіді:


244

Оператори &&і ||"коротке замикання", тобто вони не оцінюють праву частину, якщо це не потрібно.

Оператори &і |, використовуючи їх як логічні оператори, завжди оцінюють обидві сторони.

Існує лише один випадок короткого замикання для кожного оператора, і це:

  • false && ...- не варто знати, що таке права частина, тому що результат може бути лише falseнезалежно від значення, яке там є
  • true || ...- не варто знати, що таке права частина, тому що результат може бути лише trueнезалежно від значення, яке там є

Порівняємо поведінку на простому прикладі:

public boolean longerThan(String input, int length) {
    return input != null && input.length() > length;
}

public boolean longerThan(String input, int length) {
    return input != null & input.length() > length;
}

У 2-й версії використовується оператор, що не працює на короткому замиканні, &і кине NullPointerExceptionif, якщо inputє null, але перша версія повернеться falseбез винятку.


9
Я хотів би трохи продовжити цю відповідь. Оператор & = є скороченням для виразу x = x &, тому НЕ є коротким замиканням. Те саме стосується оператора | =.
Stormcloud

11
Я хотів би виділити одне, | і & є двійковими операторами, а && та || є умовними (логічними) операторами. | і & працювати над більш ніж булевими, а && та || працювати лише на булевих.
Міф

1
Вони не тільки не оцінюють вираз з правого боку, але код не виконується для того, щоб було що-небудь оцінити. Це важливий момент розуміння, якщо в іншому випадку побічний ефект буде викликаний.
mckenzm

@mckenzm Яка різниця між оціненими та виконаними?
Кронен

@Kronen Виконання може спричинити за собою більше, ніж оцінку, і призведе до побічного ефекту, такого як виняток або затримка, я плачу, що не стосується цього прикладу.
mckenzm

9

SET A використовує булеві оператори з коротким замиканням.

Що означає "коротке замикання" в контексті булевих операторів, це те, що для набору булевих b1, b2, ..., bn версії короткого замикання припинять оцінку, як тільки перша з цих булевих істин (||| ) або помилковим (&&).

Наприклад:

// 2 == 2 will never get evaluated because it is already clear from evaluating
// 1 != 1 that the result will be false.
(1 != 1) && (2 == 2)

// 2 != 2 will never get evaluated because it is already clear from evaluating
// 1 == 1 that the result will be true.
(1 == 1) || (2 != 2)

Вкажіть, будь ласка, що це стосується &&, ||працює по-іншому і припинить оцінку на перший операнд, який повертає істину;)
fge

1
Насправді, щоб бути дійсно повним, все &&, ||, &і |оцінювати зліва направо. Для набору булевих b1, b2, ..., bn, версії короткого замикання припиняють оцінку, коли перший з цих булевих істин ( ||) або false ( &&). Ба, принцип є;)
fge

@fge: Так, ти, звичайно, маєш рацію. Ваше визначення більш точне, ніж моє. Я оновив свою відповідь пропозицією у вашому коментарі. Сподіваюся, ви не заперечуєте.
afrischke

Не хвилюйтесь, знання не має значення, якщо його не поділяють.
fge

4

Коротке замикання означає, що другий оператор не перевірятиметься, якщо перший оператор вирішить кінцевий результат.

Наприклад, вираз: True || помилковий

У випадку ||, все, що нам потрібно, - це одна зі сторін, щоб бути правдою. Тож якщо ліва частина вірна, немає сенсу перевіряти праву частину, а значить, це взагалі не перевірятиметься.

Аналогічно, False && True

У випадку &&, нам потрібні обидві сторони, щоб бути правдою. Отже, якщо ліва сторона є помилковою, немає права сенсу перевіряти праву частину, відповідь має бути помилковою. А значить, це взагалі не буде перевірено.


4
boolean a = (x < z) && (x == x);

Цей вид матиме коротке замикання, тобто якщо (x < z)оцінюється як хибне, то останнє не оцінюється, aбуде помилковим, інакше &&також буде оцінено (x == x).

& є побітним оператором, але також булевим оператором AND, який не має короткого замикання.

Ви можете перевірити їх чимось так (див. Скільки разів викликається метод у кожному випадку):

public static boolean getFalse() {
    System.out.println("Method");
    return false;
}

public static void main(String[] args) {
    if(getFalse() && getFalse()) { }        
    System.out.println("=============================");        
    if(getFalse() & getFalse()) { }
}

-1 Ваша відповідь говорить про те, що &це лише побітовий оператор, але це неправда. Це також булевий "чи" оператор.
богем

@Bohemian: Дякую за голову. true & falseоцінює до хибного. Чи можете ви пояснити це "булевим" чи "оператором"? Можливо, я не отримую того, що ви намагаєтесь сказати.
Bhesh Gurung

Вибачте - я мав на увазі булевий AND, ні OR! тобто true & falseдопустимий синтаксис. -1 вилучено :)
богем

4

Простіше кажучи, коротке замикання означає зупинити оцінку, коли ви дізнаєтесь, що відповідь більше не може змінитися. Наприклад, якщо ви оцінюєте ланцюжок логічних ANDs і виявляєте a FALSEпосередині цього ланцюга, ви знаєте, що результат стане помилковим, незалежно від того, якими є значення решти виразів ланцюга. Те ж саме стосується і ланцюжка ORs: як тільки ви відкриєте a TRUE, ви дізнаєтесь відповідь відразу, і тому зможете пропустити оцінку решти виразів.

Ви вказуєте Java, що хочете короткого замикання, використовуючи &&замість &і ||замість |. Перший набір у вашій посаді - це коротке замикання.

Зауважте, що це більше, ніж спроба зберегти кілька циклів процесора: у таких виразах

if (mystring != null && mystring.indexOf('+') > 0) {
    ...
}

коротке замикання означає різницю між правильною роботою та збоєм (у випадку, коли містінг є нульовим).


2

Java пропонує два цікавих булеві оператори, які не можна знайти в більшості інших комп'ютерних мов. Ці вторинні версії AND і OR відомі як логічні оператори короткого замикання . Як видно з попередньої таблиці, оператор АБО призводить до істини, коли A є правдою, незалежно від того, що B.

Аналогічно, оператор AND призводить до помилки, коли A є хибним, незалежно від того, що це B. Якщо ви використовуєте оператори ||та &&форми, а не форми |та &форми цих операторів, Java не буде заважати оцінювати правий операнд самостійно. Це дуже корисно, коли правий операнд залежить від того, чи є правильний чи хибним лівий, щоб правильно функціонувати.

Наприклад, наступний фрагмент коду показує, як можна скористатися логічною оцінкою короткого замикання, щоб бути впевненою, що операція поділу буде дійсною перед її оцінкою:

if ( denom != 0 && num / denom >10)

Оскільки використовується форма короткого замикання AND ( &&), немає ризику спричинити ділення виключення на час виконання від нуля. Якби цей рядок коду був написаний за допомогою єдиної &версії AND, обидві сторони повинні бути оцінені, викликаючи виняток під час виконання, коли denomдорівнює нулю.

Стандартна практика використовувати форми короткого замикання І і АБО у випадках, що стосуються булевої логіки, залишаючи односимвольні версії виключно для побітових операцій. Однак з цього правила є винятки. Наприклад, розглянемо наступне твердження:

 if ( c==1 & e++ < 100 ) d = 100;

Тут, використовуючи єдиний, &гарантується, що операція приросту буде застосована до eтого, чи cдорівнює 1 чи ні.


2

Логічний АБО: - повертає true, якщо хоча б один з операндів оцінює значення true. Обидва операнди оцінюються перед застосуванням оператора АБО.

Коротке замикання АБО: - якщо операнд лівого боку повернеться істинним, він повертає істинне, не оцінюючи операнда правого боку.


2

Є кілька відмінностей між операторами &та &&операторами. Ті ж відмінності стосуються |і ||. Найголовніше, що потрібно пам’ятати, це те, що &&це логічний оператор, який стосується лише булевих операндів, в той час як& як побітовий оператор, який застосовується до цілих типів, а також до булевих.

За допомогою логічної операції ви можете зробити коротке замикання, оскільки в певних випадках (наприклад, перший операнд &&буття falseабо перший операнд ||буттяtrue ) вам не потрібно оцінювати решту виразу. Це дуже корисно для виконання таких завдань, як перевірка nullдо доступу до файлу чи методу та перевірка потенційних нулів, перш ніж ділитися ними. Для складного вираження кожна частина виразу оцінюється рекурсивно таким же чином. Наприклад, у наступному випадку:

(7 == 8) || ( (1 == 3) && (4 == 4))

Оцінюватимуться лише підкреслені частини. Щоб обчислити ||, спочатку перевірте, чи 7 == 8є true. Якби це, правий бік був би повністю пропущений. Права сторона перевіряє лише, якщо 1 == 3є false. Оскільки він є, 4 == 4його не потрібно перевіряти, і весь вираз оцінюється на false. Якби ліва частина була true, наприклад, 7 == 7замість цього 7 == 8, вся права рука була б пропущена, оскільки це ||було б усе виразtrue незалежним.

За допомогою побітової операції вам потрібно оцінити всі операнди, оскільки ви дійсно просто комбінуєте біти. Булеві фактично є однорозрядним цілим числом у Java (незалежно від того, як працює внутрішня система), і це просто збіг обставин, що ви можете зробити коротке замикання для побітових операторів у цьому одному спеціальному випадку. Причина того, що ви не можете коротко замикати загальне ціле число &або |операцію, полягає в тому, що деякі біти можуть бути включені, а деякі можуть бути вимкнені в будь-якому операнді. Щось подібне 1 & 2дає нуль, але ви не можете цього знати, не оцінюючи обидва операнди.


1
if(demon!=0&& num/demon>10)

Оскільки використовується форма короткого замикання AND (&&), немає ризику викликати виняток під час запуску, коли демон дорівнює нулю.

Реф. Java 2 П'яте видання Герберта Шильдта

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.