У меня есть длинный набор сравнений на Java, и я хотел бы знать, верны ли одно или несколько из них. Строка сравнений была длинной и сложной для чтения, поэтому я разбил ее для удобства чтения и автоматически перешел к использованию ярлыка оператора |=
вместо negativeValue = negativeValue || boolean
.
boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);
Я ожидаю, что negativeValue
это будет правда, если любое из значений <something> по умолчанию отрицательно. Это действительно так? Будет ли оно делать то, что я ожидаю? Я не видел, чтобы это упоминалось на сайте Sun или stackoverflow, но у Eclipse, похоже, нет проблем с этим, и код компилируется и запускается.
Точно так же, если бы я хотел выполнить несколько логических пересечений, мог бы я использовать &=
вместо &&
?
java
assignment-operator
compound-assignment
or-operator
Дэвид Мейсон
источник
источник
||=
оператора, но|=
представляет собой комбинацию побитового оператора или.|=
короткого замыкания будет несовместимо с другими операторами составного присваивания, поскольку этоa |= b;
будет не то же самое, чтоa = a | b;
и с обычным предупреждением об оценкеa
дважды (если это имеет значение). Мне кажется, что большого решения о языковом поведении не было||=
, поэтому я упускаю вашу точку зрения.Ответы:
Это
|=
составной оператор присваивания ( JLS 15.26.2 ) для логического оператора|
( JLS 15.22.2 ); не следует путать с условным-или||
( JLS 15.24 ). Также существуют&=
и^=
соответствующие версии составного присваивания логического логического значения&
и^
соответственно.Другими словами, для
boolean b1, b2
этих двух эквивалентов:Разница между логическими операторами (
&
и|
) по сравнению с их условными аналогами (&&
и||
) заключается в том, что первые не «закорачивают»; последние делают. То есть:&
и|
всегда оценивать оба операнда&&
и условно||
оценить правый операнд ; правый операнд оценивается только в том случае, если его значение может повлиять на результат двоичной операции. Это означает, что правильный операнд НЕ оценивается, когда:&&
оценивается какfalse
false
)||
оценивается какtrue
true
)Итак, возвращаясь к исходному вопросу, да, эта конструкция действительна, и хотя
|=
это не совсем эквивалентный ярлык для=
и||
, она вычисляет то, что вы хотите. Поскольку правая часть|=
оператора в вашем использовании представляет собой простую операцию целочисленного сравнения, тот факт, что|
не происходит короткого замыкания, не имеет значения.Бывают случаи, когда короткое замыкание желательно или даже необходимо, но ваш сценарий не входит в их число.
К сожалению, в отличие от некоторых других языков, в Java нет
&&=
и||=
. Это обсуждалось в вопросе Почему в Java нет составных версий присваивания для операторов условного и и условного или операторов? (&& =, || =) .источник
|
Это не «сокращающий» (или сокращающий) оператор в том смысле, в котором || и && есть (в том смысле, что они не будут оценивать RHS, если они уже знают результат на основе LHS), но он будет делать то, что вы хотите, с точки зрения работы .
В качестве примера разницы этот код подойдет, если он
text
равен нулю:boolean nullOrEmpty = text == null || text.equals("")
тогда как это не будет:
boolean nullOrEmpty = false; nullOrEmpty |= text == null; nullOrEmpty |= text.equals(""); // Throws exception if text is null
(Очевидно, вы могли бы сделать это
"".equals(text)
в этом конкретном случае - я просто пытаюсь продемонстрировать принцип.)источник
У вас может быть только одно заявление. Выраженный в нескольких строках, он читается почти так же, как ваш пример кода, только менее обязательно:
boolean negativeValue = defaultStock < 0 | defaultWholesale < 0 | defaultRetail < 0 | defaultDelivery < 0;
Для простейших выражений использование
|
может быть быстрее, чем||
потому, что даже если оно избегает сравнения, оно означает неявное использование ветки, а это может быть во много раз дороже.источник
Хотя это может быть излишним для вашей проблемы, библиотека Guava имеет приятный синтаксис с
Predicate
s и выполняет короткую оценку or / andPredicate
s.По сути, сравнения превращаются в объекты, упаковываются в коллекцию, а затем повторяются. Для предикатов или первое истинное попадание возвращается с итерации, и наоборот для и.
источник
Если речь идет о читабельности, у меня есть концепция отделения проверенных данных от логики тестирования. Пример кода:
// 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; }
Код выглядит более подробным и понятным. Вы даже можете создать массив при вызове метода, например:
checkIfAnyNegative(new DataType[] { defaultStock, defaultWholesale, defaultRetail, defaultDelivery });
Он более читабелен, чем «строка сравнения», а также имеет преимущество в производительности за счет короткого замыкания (за счет выделения массива и вызова метода).
Изменить: еще большей читабельности можно просто добиться, используя параметры varargs:
Сигнатура метода будет:
boolean checkIfAnyNegative(DataType ... data)
И звонок мог выглядеть так:
источник
Это старый пост, но чтобы дать новичкам другую перспективу, я хотел бы привести пример.
Я думаю, что наиболее распространенным вариантом использования подобного составного оператора будет
+=
. Я уверен, что все мы писали что-то вроде этого:int a = 10; // a = 10 a += 5; // a = 15
Какой в этом был смысл? Суть заключалась в том, чтобы избежать шаблонов и устранить повторяющийся код.
Итак, следующая строка делает то же самое, избегая
b1
двойного ввода переменной в одной строке.источник
longNameOfAccumulatorAVariable += 5;
vs.longNameOfAccumulatorAVariable = longNameOfAccumulatorVVariable + 5;
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale, defaultRetail, defaultDelivery); int minParam = Collections.min (params); negativeValue = minParam < 0;
источник
negativeValue = defaultStock < 0 || defaultWholesale < 0
и т. Д. Помимо неэффективности всего происходящего здесь упаковки и упаковки, мне не так легко понять, что на самом деле означает ваш код.|| логическое логическое ИЛИ
| побитовое ИЛИ
| = побитовое включающее ИЛИ и оператор присваивания
Причина, по которой | = не сокращается, заключается в том, что он выполняет побитовое ИЛИ, а не логическое ИЛИ. То есть:
Учебник для операторов Java
источник
|
представляет собой целочисленное побитовое ИЛИ, но также является логическим ИЛИ - см. Спецификацию языка Java 15.22.2.