Operator skrótu "or-assignment" (|=) w Javie

Mam do zrobienia długi zestaw porównań w Javie i chciałbym wiedzieć, czy jedno lub więcej z nich wyjdzie na jaw. Ciąg porównań był długi i trudny do odczytania, więc złamałem go dla czytelności i automatycznie poszedłem użyć operatora skrótu |= zamiast negativeValue = negativeValue || boolean.

boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);

Oczekuję, że negativeValue będzie prawdziwa, jeśli którakolwiek z domyślnych wartości jest ujemna. Czy to ważne? Zrobi to, czego oczekuję? Nie widze tego na stronie Sun ' a czy stackoverflow, ale Eclipse wygląda na to, że nie ma z tym problemu, a kod kompiluje się i uruchamia.


Podobnie, gdybym chciał wykonać kilka skrzyżowań logicznych, czy mógłbym użyć &= zamiast &&?

Author: Raedwald, 2010-03-21

8 answers

|= jest operatorem przypisania złożonego ( JLS 15.26.2) dla operatora logicznego boolean| (JLS 15.22.2); nie mylić z warunkowym-lub || (JLS 15.24). Istnieją również &= i ^= odpowiadające złożonej wersji logicznego przypisania & i ^ odpowiednio.

Innymi słowy, dla boolean b1, b2 te dwa są równoważne:

 b1 |= b2;
 b1 = b1 | b2;

Różnica między operatorami logicznymi (& i |) w porównaniu do ich warunkowych odpowiedników (&& i ||) jest to, że pierwsze nie "skracają", a drugie tak. Czyli:

  • & oraz | zawsze oceniaj oba operandy
  • && i || oceniają prawe operand warunkowo; prawe operand jest oceniane tylko wtedy, gdy jego wartość może wpłynąć na wynik operacji binarnej. Oznacza to, że właściwy operand nie jest oceniany, gdy:
    • lewy operand && ocenia do false
      • (ponieważ bez względu na to, do jakiego WŁAŚCIWEGO operandu jest ewaluowany, całe wyrażenie jest false)
    • lewy operand || ocenia na true
      • (ponieważ bez względu na to, do jakiego WŁAŚCIWEGO operandu jest ewaluowany, całe wyrażenie jest true)

Wracając więc do twojego pierwotnego pytania, tak, ten konstrukt jest prawidłowy i chociaż |= nie jest dokładnie odpowiednikiem skrótu dla = I ||, to oblicza to, co chcesz. Ponieważ prawa strona operatora |= w Twoim użyciu jest prostą operacją porównywania liczb całkowitych, fakt, że | nie jest skrótem jest nieistotny.

Zdarzają się przypadki, kiedy krótszy obieg jest pożądany, a nawet wymagany, ale twój scenariusz nie jest jednym z nich.

Szkoda, że w przeciwieństwie do innych języków Java nie posiada &&= i ||=. Zostało to omówione w pytaniu dlaczego Java nie ma compound przypisanie wersji warunkowych-i i warunkowych-czy operatorów? (&&=, ||=).

 184
Author: polygenelubricants,
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
2017-05-23 12:34:08

Nie jest operatorem" skrótu " (lub zwarcia) w taki sposób, że | / i & & są (w tym, że nie będą oceniać RHS, jeśli znają już wynik na podstawie LHS), ale zrobi to, co chcesz pod względem działa .

Jako przykład różnicy, ten kod będzie w porządku, jeśli text jest null:

boolean nullOrEmpty = text == null || text.equals("")

Natomiast to nie będzie:

boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null

(Oczywiście możesz zrobić "".equals(text) w tym konkretnym przypadku-staram się tylko zademonstrować zasadę.)

 16
Author: Jon Skeet,
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
2010-03-21 09:12:10

Możesz mieć tylko jedno oświadczenie. Wyrażony w wielu wierszach czyta prawie dokładnie tak, jak Twój przykładowy kod, tylko mniej imperatywny:

boolean negativeValue
    = defaultStock < 0 
    | defaultWholesale < 0
    | defaultRetail < 0
    | defaultDelivery < 0;

Dla najprostszych wyrażeń, użycie | może być szybsze niż ||, ponieważ nawet jeśli unika się porównywania, oznacza użycie gałęzi w domyśle i to może być wielokrotnie droższe.

 3
Author: Peter Lawrey,
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
2014-09-17 18:31:54

Chociaż może to być przesada dla Twojego problemu, biblioteka Guava ma jakąś ładną składnię z Predicate s i robi zwarcie oceny or / I Predicate s.

Zasadniczo porównania są przekształcane w obiekty, pakowane do kolekcji, a następnie powtarzane. Dla predykatów or, pierwszy prawdziwy hit powraca z iteracji i odwrotnie Dla and.

 1
Author: Carl,
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
2010-03-22 14:28:50

Jeśli chodzi o czytelność, mam pojęcie oddzielenia testowanych danych od logiki testowania. Przykład kodu:

// declare data
DataType [] dataToTest = new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
}

// define logic
boolean checkIfAnyNegative(DataType [] data) {
    boolean negativeValue = false;
    int i = 0;
    while (!negativeValue && i < data.length) {
        negativeValue = data[i++] < 0;
    }
    return negativeValue;
}

Kod wygląda bardziej zwięzle i jasno. Można nawet utworzyć tablicę w wywołaniu metody, jak to:

checkIfAnyNegative(new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
});

Jest bardziej czytelny niż 'comparison string' , a także ma przewagę wydajności zwarcia (kosztem alokacji tablicy i wywołania metody).

Edit: Jeszcze większą czytelność można po prostu osiągnąć za pomocą parametry varargs:

Podpis metody będzie:

boolean checkIfAnyNegative(DataType ... data)

A wywołanie może wyglądać tak:

checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );
 1
Author: Krzysztof Jabłoński,
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-04-26 08:11:53
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale, 
                                       defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;
 0
Author: Roman,
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
2010-03-21 09:21:31

|| logiczny boolean OR
/ bitowe lub

| = bitowy inkluzywny operator OR i przypisania

Powodem, dla którego | = nie skraca się, jest to, że robi bitowe lub nie logiczne OR. To znaczy:


C |= 2 is same as C = C | 2

Tutorial dla operatorów Javy

 0
Author: oneklc,
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-01-11 19:15:04

To stary post, ale w celu zapewnienia innej perspektywy dla początkujących, chciałbym podać przykład.

Myślę, że najczęstszym przypadkiem użycia podobnego operatora złożonego byłoby +=. Jestem pewien, że wszyscy napisaliśmy coś takiego:

int a = 10;   // a = 10
a += 5;   // a = 15

Jaki był tego cel? Miało to na celu uniknięcie dwukrotnego zapisu zmiennej a w tej samej linii. (Czy brakuje mi tu czegoś lepszego?)

Więc następny wiersz robi dokładnie to samo, unikając wpisywania zmiennej b1 dwa razy w ta sama linia.

b1 |= b2;
 0
Author: oxyt,
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-04-17 08:53:57