Ярлык “или-присвоение” (|=) оператор в Java

У меня есть длинный набор сравнений, чтобы сделать в Java, и я хотел бы знать, выходит ли один или несколько из них как верный. Строка сравнений была длинной и трудной читать, таким образом, я разбил ее для удобочитаемости и автоматически пошел для использования оператора ярлыка |= вместо negativeValue = negativeValue || boolean.

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

Я ожидаю negativeValue чтобы быть верным, если какое-либо значение по умолчанию <что-то> оценивает, отрицательны. Действительно ли это допустимо? Это сделает то, что я ожидаю? Я не мог видеть, что это упомянуло на сайте или stackoverflow Sun, но Eclipse, кажется, не имеет проблему с ним и компиляции кода и выполнения.


Точно так же, если я хотел выполнить несколько логических пересечений, мог я использовать &= вместо &&?

84
задан Raedwald 14 July 2014 в 22:09
поделиться

5 ответов

|= - это составной оператор присваивания (JLS 15.26.2) для логического оператора булевой логики | (JLS 15.22.2); не путать с условным-или || (JLS 15.24). Существуют также &= и ^=, соответствующие составной версии присваивания булевых логических & и ^ соответственно.

Другими словами, для булевых b1, b2 эти два оператора эквивалентны:

 b1 |= b2;
 b1 = b1 | b2;

Разница между логическими операторами (& и |) и их условными аналогами (&& и ||) в том, что первые не "замыкаются", а вторые замыкаются. То есть:

  • & и | всегда оценивают оба операнда
  • && и || оценивают правый операндусловно; правый операнд оценивается только если его значение может повлиять на результат бинарной операции. Это означает, что правый операнд НЕ оценивается, если:
    • Левый операнд && оценивается в false
      • (поскольку независимо от того, во что оценивается правый операнд, все выражение равно false)
    • Левый операнд || оценивается в true
      • (поскольку независимо от того, во что оценивается правый операнд, все выражение равно true)

Так что, возвращаясь к вашему первоначальному вопросу, да, эта конструкция действительна, и хотя |= не совсем эквивалентное сокращение для = и ||, оно вычисляет то, что вы хотите. Поскольку правая часть оператора |= в вашем случае является простой операцией сравнения целых чисел, тот факт, что | не является сокращением, несущественен.

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

К сожалению, в отличие от некоторых других языков, в Java нет &&= и ||=. Это обсуждалось в вопросе Почему в Java нет составных вариантов присваивания операторов условного-и и условного-или? (&&=, ||=).

195
ответ дан 24 November 2019 в 08:28
поделиться

У вас может быть только одно утверждение. Выраженный в нескольких строках, он читается почти так же, как ваш пример кода, только менее императивен:

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

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

3
ответ дан 24 November 2019 в 08:28
поделиться
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale, 
                                       defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;
0
ответ дан 24 November 2019 в 08:28
поделиться

Это не оператор "быстрого доступа" (или короткого замыкания) в том смысле, в котором || и && (в том смысле, что они не будут оценивать RHS, если они уже знают результат на основе LHS), но он будет делать то, что вы хотите, с точки зрения работы .

В качестве примера разницы этот код подойдет, если text имеет значение null:

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

, тогда как это не будет:

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

(Очевидно, вы могли бы сделать "". Equals (текст) для этого конкретного случая - я просто пытаюсь продемонстрировать принцип.)

16
ответ дан 24 November 2019 в 08:28
поделиться

Хотя это может быть излишним для вашей проблемы, библиотека Guava имеет хороший синтаксис с Predicate s и выполняет оценку короткого замыкания или / и Predicate ] с.

По сути, сравнения превращаются в объекты, упаковываются в коллекцию, а затем повторяются. Для предикатов или первое истинное попадание возвращается с итерации, и наоборот для и.

1
ответ дан 24 November 2019 в 08:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: