Так что для бинарных операторов в булевых, Java имеет &
, |
, ^
, &&
и ||
.
Кратко подведем итоги того, чем они занимаются:
- JLS 15.22.2 Булевы логические операторы &, ^ и |
- JLS 15.23 Оператор условного И &&
- JLS 15.24 Оператор условного ИЛИ ||
Для
&
результирующее значение будет,true
если оба значения операнда равныtrue
; в противном случае результат будетfalse
.Для
|
результирующее значение будет,false
если оба значения операнда равныfalse
; в противном случае результат будетtrue
.Для
^
, значение результатаtrue
если значения операндов разные; в противном случае результат будетfalse
.
&&
Оператор подобен ,&
но оценивает ее правый операнд только , если значение его левого операнда являетсяtrue
.
||
Оператор подобен|
, но вычисляет правый операнд только , если значение его левого операнда являетсяfalse
.
Теперь из всех 5 у 3 есть составные версии присваивания, а именно |=
, &=
и ^=
. Итак, мой вопрос очевиден: почему Java не поддерживает &&=
и ||=
? Я считаю, что мне нужно больше, чем мне нужно&=
и |=
.
И я не думаю, что «потому что это слишком долго» - хороший ответ, потому что в Java есть >>>=
. Для этого упущения должна быть более веская причина.
Начиная с 15.26 Операторы присваивания :
Есть 12 операторов присваивания; [...]
= *= /= %= += -= <<= >>= >>>= &= ^= |=
Было сделано замечание, что если &&=
и ||=
будут реализованы, то это будут единственные операторы, которые сначала не оценивают правую часть. Я считаю ошибочным представление о том, что составной оператор присваивания сначала оценивает правую часть.
Начиная с версии 15.26.2 Операторы составного присваивания :
Составное выражение присваивания формы
E1 op= E2
эквивалентноE1 = (T)((E1) op (E2))
, гдеT
- типE1
, за исключением того, чтоE1
оно оценивается только один раз.
В качестве доказательства следующий фрагмент выдает a NullPointerException
, а не ArrayIndexOutOfBoundsException
.
int[] a = null;
int[] b = {};
a[0] += b[-1];
источник
Ответы:
Причина
Операторы
&&=
и||=
недоступны в Java, потому что для большинства разработчиков эти операторы:Пример для
&&=
Если в Java разрешен
&&=
оператор, то этот код:bool isOk = true; //becomes false when at least a function returns false isOK &&= f1(); isOK &&= f2(); //we may expect f2() is called whatever the f1() returned value
будет эквивалентно:
bool isOk = true; if (isOK) isOk = f1(); if (isOK) isOk = f2(); //f2() is called only when f1() returns true
Этот первый код подвержен ошибкам, потому что многие разработчики думают, что
f2()
он всегда вызывается независимо от возвращаемого значения f1 (). Это какbool isOk = f1() && f2();
wheref2()
вызывается только приf1()
возвратеtrue
.Если разработчик хочет,
f2()
чтобы его вызывали только послеf1()
возвратаtrue
, второй код выше менее подвержен ошибкам.Else
&=
достаточно, потому что разработчик хочет,f2()
чтобы его всегда вызывали:Тот же пример, но для
&=
bool isOk = true; isOK &= f1(); isOK &= f2(); //f2() always called whatever the f1() returned value
Более того, JVM должна запускать этот приведенный выше код как следующий:
bool isOk = true; if (!f1()) isOk = false; if (!f2()) isOk = false; //f2() always called
Сравнить
&&
и&
результатыЯвляются ли результаты операторов
&&
и&
одинаковыми при применении к логическим значениям?Давайте проверим, используя следующий код Java:
public class qalcdo { public static void main (String[] args) { test (true, true); test (true, false); test (false, false); test (false, true); } private static void test (boolean a, boolean b) { System.out.println (counter++ + ") a=" + a + " and b=" + b); System.out.println ("a && b = " + (a && b)); System.out.println ("a & b = " + (a & b)); System.out.println ("======================"); } private static int counter = 1; }
Вывод:
1) a=true and b=true a && b = true a & b = true ====================== 2) a=true and b=false a && b = false a & b = false ====================== 3) a=false and b=false a && b = false a & b = false ====================== 4) a=false and b=true a && b = false a & b = false ======================
Поэтому ДА , мы можем заменить
&&
на&
для логических значений ;-)Так что лучше использовать
&=
вместо&&=
.То же самое для
||=
Те же причины , как для
&&=
:оператора
|=
меньше подвержены ошибкам , чем||=
.Если разработчик
f2()
не хочет, чтобы его вызывали поf1()
возвращенииtrue
, я советую следующие альтернативы:// here a comment is required to explain that // f2() is not called when f1() returns false, and so on... bool isOk = f1() || f2() || f3() || f4();
или же:
// here the following comments are not required // (the code is enough understandable) bool isOk = false; if (!isOK) isOk = f1(); if (!isOK) isOk = f2(); //f2() is not called when f1() returns false if (!isOK) isOk = f3(); //f3() is not called when f1() or f2() return false if (!isOK) isOk = f4(); //f4() is not called when ...
источник
&
и&&
дают те же результаты. Большое спасибо за ваш отзыв. Тебе нравится мой ответ? Ура.if (a) a = b
для скоростиa&=b;
это быстрее, чемif(a) a=b;
при использовании значений, хранящихся в регистрах процессора. Однако, если онb
находится во внешней памяти (не кэширован), тоif(a) a=b;
быстрее. Вы это имеете в виду? Пожалуйста, предоставьте больше примеров кода ;-) Мне интересно ваше мнение. Увидимся. CheersisOK &&= f2();
я бы хотел, чтобы он замкнулся, как и&&
делает.A = A op B
, чтобы все прекрасно знали, что они делают, и могли сами позаботиться о последствиях. Если бы ваши причины действительно были причиной его отсутствия, я бы воспринял это как нежелательное покровительство. Однако я хочу поблагодарить вас за добавление строки,bool isOk = f1() || f2() || f3() || f4();
потому что это то, что я должен был ослепить, чтобы увидеть себя.Наверное, потому что что-то вроде
x = false; x &&= someComplexExpression();
похоже, что это должно быть присвоение
x
и оценкаsomeComplexExpression()
, но тот факт, что оценка зависит от значенияx
не очевиден из синтаксиса.Также потому, что синтаксис Java основан на C, и никто не видел острой необходимости добавлять эти операторы. В любом случае вам, вероятно, будет лучше с оператором if.
источник
x() && y()
похоже, следует оценивать обе стороны выражения. Очевидно, люди принимают это за&&
короткое замыкание, так что это тоже должно следовать&&=
.a -= b;
будет работать совершенно иначе, чемa &&= b;
.Так в Java, потому что так в C.
Теперь вопрос, почему это так в C, заключается в том, что, когда & и && стали разными операторами (когда-то предшествовавшим происхождению C от B), разнообразие операторов & = было просто упущено.
Но у второй части моего ответа нет источников, подтверждающих это.
источник
Во многом потому, что синтаксис Java основан на C (или, по крайней мере, на семействе C), а в C все эти операторы присваивания компилируются в арифметические или побитовые инструкции сборки в одном регистре. Версия с оператором присваивания избегает временных затрат и, возможно, дает более эффективный код на ранних неоптимизирующих компиляторах. Логический оператор (как они называются в C) эквиваленты (
&&=
и||=
) не имеют столь очевидного соответствия отдельным инструкциям сборки; они обычно расширяются до последовательности инструкций теста и перехода.Интересно, что в таких языках, как ruby , есть || = и && =.
Изменить: терминология отличается между Java и C
источник
&
,|
и^
;&&
и||
являются условными операторами.bool
типа. Это 20 лет в истории языка без bool. Для этого не было причин&&=
. побитовых операций было достаточно.Одна из первоначальных целей Java заключалась в том, чтобы быть «простой, объектно-ориентированной и знакомой». Применительно к этому случаю & = знакомо (оно есть в C, C ++, и в данном контексте слово «знакомый» означает знакомый тем, кто знаком с этими двумя).
&& = было бы незнакомо, и это было бы непросто в том смысле, что разработчики языка не пытались продумать каждый оператор, который они могли бы добавить в язык, поэтому меньше дополнительных операторов проще.
источник
Для булевых переменных && и || будет использовать оценку короткого замыкания, в то время как & и | нет, поэтому можно ожидать, что && = и || = также будут использовать оценку короткого замыкания. Для этого есть хороший вариант использования. Если вы повторяете цикл, вы хотите быть быстрым, эффективным и кратким.
Вместо того, чтобы писать
foreach(item in coll) { bVal = bVal || fn(item); // not so elegant }
Я хочу написать
foreach(item in coll) { bVal ||= fn(item); // elegant }
и знайте, что как только bVal истинно, fn () не будет вызываться до конца итераций.
источник
if (fn(item)) { bVal = true; break; }
.'
&
' и '&&
' - это не то же самое, что '&&
' - это сокращенная операция, которая не будет работать, если первый операнд ложный, в то время как '&
' будет делать это в любом случае (работает как с числом, так и с логическим).Я согласен с тем, что в существовании больше смысла, но не так уж и плохо, если его нет. Думаю, его там не было, потому что в C его нет.
На самом деле не могу понять почему.
источник
Это разрешено в Ruby.
Если бы я догадывался, я бы сказал, что он не часто используется, поэтому не был реализован. Другое объяснение может заключаться в том, что парсер смотрит только на символ перед =
источник
Я не могу придумать лучшей причины, чем «Это выглядит невероятно уродливо!»
источник
&&=
себя некрасивым&
проверяет оба операнда, это побитовый оператор. Java определяет несколько побитовых операторов, которые могут применяться к целочисленным типам long, int, short, char и byte.
&&
перестает оценивать, оценивается ли первый операнд как ложное, поскольку результат будет ложным, это логический оператор. Его можно применять к логическим значениям.
Оператор && похож на оператор &, но может сделать ваш код более эффективным. Поскольку оба выражения, сравниваемые оператором &, должны быть истинными, чтобы все выражение было истинным, нет причин оценивать второе выражение, если первое возвращает ложь. Оператор & всегда вычисляет оба выражения. Оператор && вычисляет второе выражение, только если первое выражение истинно.
Наличие оператора присваивания && = не добавит языку новых функциональных возможностей. Арифметика побитового оператора намного более выразительна, вы можете выполнять целочисленную побитовую арифметику, в том числе логическую арифметику. Логические операторы могут просто выполнять логическую арифметику.
источник
Брайан Гетц (архитектор языка Java в Oracle) написал :
источник
a & b и a && b - это не одно и то же.
a && b - это логическое выражение, которое возвращает логическое значение, а a & b - побитовое выражение, возвращающее int (если a и b - это целые числа).
как вы думаете, они такие же?
источник