Java operator logiczny zwarcie

Który zbiór jest zwarciem i co dokładnie oznacza, że złożone wyrażenie warunkowe jest zwarciem?

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

}
Author: Chris Martin, 2012-01-06

9 answers

Operatory && i || "zwarcie", co oznacza, że nie oceniają prawej strony, jeśli nie jest to konieczne.

Operatory & i |, gdy są używane jako operatory logiczne, zawsze oceniają obie strony.

Istnieje tylko jeden przypadek zwarcia dla każdego operatora i są to:

  • false && ... - nie trzeba wiedzieć, co to jest Prawa strona, wynik musi być false
  • true || ... - nie trzeba wiedzieć, co prawo strony jest, wynik musi być true

Porównajmy zachowanie w prostym przykładzie:

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

Druga wersja używa operatora bez zwarcia & i rzuca NullPointerException jeśli input jest null, ale pierwsza wersja zwróci false bez wyjątku;

 198
Author: Bohemian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-16 19:56:54

SET a używa zwarciowych operatorów logicznych.

Co "zwarcie" oznacza w kontekście operatorów logicznych jest to, że dla zbioru logicznych b1, b2, ..., BN, wersje zwarciowe przestaną być ewaluowane, gdy pierwsza z tych wartości logicznych będzie true ( / / ) lub false (&&).

Na przykład:

// 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)
 9
Author: afrischke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-06 15:37:36

Zwarcie oznacza, że drugi operator nie będzie sprawdzany, jeśli pierwszy operator zdecyduje o ostatecznym wyniku.

Np. wyrażenie to: True / / False

W przypadku|/, wystarczyone of the side to prawda. Więc jeśli lewa strona jest prawdziwa, nie ma sensu sprawdzać prawej strony, a więc to nie będzie sprawdzane w ogóle.

Podobnie, False & & True

W przypadku&&, potrzebujemy obie strony to prawda. Więc jeśli lewa strona jest fałszywa, nie ma sensu sprawdzać prawej strony, odpowiedź musi być fałszywa. I dlatego nie będzie to w ogóle sprawdzane.

 4
Author: Bhushan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-06 15:10:46
boolean a = (x < z) && (x == x);

Ten rodzaj zwarcia, co oznacza, że jeśli (x < z) oceni na false, to ta ostatnia nie zostanie oceniona, a będzie false, w przeciwnym razie && oceni również (x == x).

& jest operatorem bitowym, ale także operatorem boolowskim i nie zwarciowym.

Możesz je przetestować w następujący sposób (zobacz, ile razy metoda jest wywoływana w każdym przypadku):

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()) { }
}
 4
Author: Bhesh Gurung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-06 15:37:48

Mówiąc wprost, zwarcie oznacza zatrzymanie oceny, gdy wiesz, że odpowiedź nie może się już zmienić. Na przykład, jeśli oceniasz łańcuch logicznych AND s i odkrywasz FALSE w środku tego łańcucha, wiesz, że wynik będzie fałszywy, bez względu na to, jakie są wartości pozostałych wyrażeń w łańcuchu. To samo dotyczy łańcucha OR s: gdy odkryjesz TRUE, znasz odpowiedź od razu, więc możesz pominąć ocenę reszty wyrażenia.

Wskazujesz Javie, że chcesz zwarcia, używając && zamiast & i || zamiast |. Pierwszy zestaw w Twoim poście to zwarcie.

Zauważ, że jest to więcej niż próba zapisania kilku cykli procesora: w wyrażeniach takich jak ten

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

Zwarcie oznacza różnicę między prawidłowym działaniem a awarią (w przypadku, gdy mystring jest null).

 3
Author: dasblinkenlight,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-16 14:12:03

Java dostarcza dwóch interesujących operatorów logicznych, których nie można znaleźć w większości innych języków komputerowych. Te dodatkowe wersje AND I OR są znane jako operatory logiczne zwarcia . Jak widać z poprzedniej tabeli, operator OR powoduje true, gdy A jest true, bez względu na to, czym jest B.

Podobnie operator AND powoduje false, gdy A jest false, bez względu na to, co jest B. Jeśli używasz formularzy || i &&, zamiast formularzy | i & tych operatorów, Java nie będzie się trudzić samą oceną prawego operanda. Jest to bardzo przydatne, gdy prawostronny operand zależy od tego, czy lewy operand jest prawdziwy czy fałszywy, aby poprawnie funkcjonować.

Na przykład poniższy fragment kodu pokazuje, w jaki sposób można skorzystać z logicznej oceny zwarcia, aby upewnić się, że operacja podziału będzie ważna przed jej oceną:

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

Ponieważ używana jest forma zwarciowa AND (&&), nie ma ryzyka spowodowania czasu pracy wyjątek od dzielenia przez zero. Gdyby ten wiersz kodu został napisany przy użyciu pojedynczej wersji & AND, obie strony musiałyby zostać ocenione, powodując wyjątek w czasie wykonywania, gdy denom wynosi zero.

Standardową praktyką jest używanie zwarciowych form AND and OR w przypadkach obejmujących logikę Boolowską, pozostawiając wersje jednowarstwowe wyłącznie dla operacji bitowych. Istnieją jednak wyjątki od tej reguły. Na przykład rozważ następujące kwestie wypowiedź:

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

Tutaj, użycie pojedynczego & zapewnia, że operacja przyrostu zostanie zastosowana do e, czy c jest równa 1, czy nie.

 2
Author: Dileep Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-24 19:48:55

Logical OR: - zwraca true, jeśli przynajmniej jeden z operandów ocenia na true. Oba operandy są oceniane przed zastosowaniem operatora OR.

Short Circuit OR: - jeśli operand po lewej stronie zwraca true, zwraca true bez oceny operandu po prawej stronie.

 2
Author: dimansha malrindu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-09 16:25:34
if(demon!=0&& num/demon>10)

Ponieważ używana jest forma zwarcia AND (&&), nie ma ryzyka wywołania wyjątku w czasie wykonywania, gdy demon ma wartość zero.

Ref. Java 2 Fifth Edition by Herbert Schildt

 1
Author: Nitesh Verma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-12 05:07:48

Istnieje kilka różnic między operatorami & i &&. Te same różnice dotyczą | i ||. Najważniejszą rzeczą, o której należy pamiętać, jest to, że && jest operatorem logicznym, który ma zastosowanie tylko do operandów logicznych, podczas gdy & jest operatorem bitowym, który ma zastosowanie zarówno do typów całkowitych, jak i booleanów.

Z operacją logiczną można wykonać zwarcie, ponieważ w pewnych przypadkach (np. pierwszy operand && jest false, lub pierwszy operand || jest true), nie trzeba oceniać reszty wyrażenia. Jest to bardzo przydatne do wykonywania takich czynności jak sprawdzanie null przed uzyskaniem dostępu do pliku lub metody oraz sprawdzanie potencjalnych zer przed podzieleniem przez nie. Dla wyrażenia złożonego każda część wyrażenia jest obliczana rekurencyjnie w ten sam sposób. Na przykład w następującym przypadku:

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

Tylko podkreślone części będą oceniane. Aby obliczyć ||, najpierw sprawdź, czy 7 == 8 jest true. Gdyby tak było, prawa strona zostałaby całkowicie pominięta. Prawa strona sprawdza tylko, czy 1 == 3 jest false. Ponieważ jest, 4 == 4 nie musi być sprawdzane, a całe wyrażenie jest ewaluowane na false. Gdyby lewa strona była true, np. 7 == 7 zamiast 7 == 8, cała prawa strona zostałaby pominięta, ponieważ całe wyrażenie || byłoby true niezależnie od tego.

Z bitową operacją, musisz ocenić wszystkie operandy, ponieważ jesteś naprawdę po prostu łączenie bitów. Wartości logiczne są w praktyce jednobitową liczbą całkowitą w Javie (bez względu na to, jak działają wewnętrzne układy) i jest tylko zbiegiem okoliczności, że w tym szczególnym przypadku można wykonać zwarcie dla operatorów bitowych. Powodem, dla którego nie można zwarć ogólnej liczby całkowitej & lub |, jest to, że niektóre bity mogą być włączone, a niektóre mogą być wyłączone w każdym z operandów. Coś w rodzaju 1 & 2 daje zero, ale nie można tego wiedzieć bez oceny obu operandów.

 0
Author: Mad Physicist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-05 17:22:15