Вопрос по conditional-operator, java, compound-assignment, assignment-operator, short-circuiting – Почему в Java нет составных версий условных и условных операторов? (&& =, || =)

75

Так что для бинарных операторов на логических, Java имеет,,&|^&& а также .||

Позволять'Подведем итог, что они делают здесь кратко:

JLS 15.22.2 Булевы логические операторы и, ^ и |JLS 15.23 Условно-операторный оператор &&JLS 15.24 Оператор условного или ||

За&, значение результатаtrue если оба значения операндаtrue; в противном случае результатfalse

За|, значение результатаfalse если оба значения операндаfalse; в противном случае результатtrue

За^, значение результатаtrue если значения операндов различны; в противном случае результатfalse

&& оператор как& но оценивает его правый операнд, только если значение его левого операнда равно.true

|| оператор как|, но оценивает его правый операнд, только если значение его левого операнда равно.false

Теперь среди всех 5, 3 из них есть составные версии присваивания, а именно:|=&= а также^=, Так что мой вопрос очевиден: почему нетЯва обеспечивает&&= а также||= также? Я считаю, что мне нужно больше, чем мне нужно&= а также .|=

И я нене думаю, что "потому что это'слишком долго хороший ответ, потому что Java имеет>>>=, Должна быть более веская причина для этого упущения.

От15.26 Операторы присваивания:

Есть 12 операторов присваивания; [...]= *= /= %= += -= = >>>= &= ^= |=

Был сделан комментарий, что если&&= а также||= были бы реализованы, тогда это были бы единственные операторы, которые не оценивают правую часть в первую очередь. Я считаю, что представление о том, что составной оператор присваивания сначала оценивает правую часть, является ошибкой.

От15.26.2 Операторы сложного присваивания:

Составное выражение присваивания формыE1 op= E2 эквивалентноE1 = (T)((E1) op (E2)), гдеT это типE1, Кроме этогоE1 оценивается только один раз.

В качестве доказательства следующий фрагмент кодаNullPointerExceptionнеArrayIndexOutOfBoundsException

    int[] a = null;
    int[] b = {};
    a[0] += b[-1];
@ Аарон: а = а & б. Это'написано в вопросе Federico klez Culloca
возможный дубликатПочему "&& =" Оператор не существует? Josh Lee
Что значит &= значит? Кто-нибудь, пожалуйста, можете сказать мне? Tarik
@jleedev: Этот вопрос старше, но у него больше голосов и входящих ссылок. Я'скажу, если естьЛюбое слияние, слияние старого с этим (да, это может быть сделано). polygenelubricants

Ваш Ответ

11   ответов
0

Если бы я догадался, я бы сказал, что это не часто используется, так что это не былот реализовано. Другое объяснение может заключаться в том, что синтаксический анализатор смотрит только на символ перед =

правда. Я не'не думаю о тех. Я думаю, что единственное объяснение заключается в том, как часто это используется. zzawaideh
Java поддерживает <<=, >>= и >>>=, так что это неСтрого верно. Yishai
8

Теперь вопрос, почему это так в C, потому что, когда & а также && стали разные операторы (когда-то предшествовавшие C 'S спуск с B), &= разнообразие операторов было просто упущено.

Но вторая часть моего ответа не имеет источников, подтверждающих это.

На смешной стороне - вопрос был недавно задан на форуме C; и этот ответ был связан (хотя и не помечен как дубликат), что завершает круговой аргумент! UKMonkey
3

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

Вместо того чтобы писать

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

Наверное, потому что что-то вроде

x = false;
x &&= someComplexExpression();

выглядит как это должно быть назначениеx и оцениваяsomeComplexExpression(), но тот факт, что оценка зависит от стоимостиx ISN»Это видно из синтаксиса.

Кроме того, потому что JavaСинтаксис s основан на C, и никто не видел острой необходимости добавлять эти операторы. Вы'Во всяком случае, лучше бы с утверждением if.

Я думаю, говоря, что они нет, потому что дизайнеры просто следовали за приоритетом, установленным C, вводит в заблуждение, так как они добавили>>> а также>>>=, которые являются совершенно новыми. polygenelubricants
@PSpeed: в этом случаеa -= b; будет работать совершенно иначе, чем.a &&= b; David Thornley
@polygene Это 'справедливо Как что-то выглядит в зависимости от того, что выхотя, я думаю, что они неЯ не хочу добавлять что-то новое. В C / C ++ / Java / C # мне нравится то, что основной синтаксис выражений практически идентичен. Josh Lee
Я думаю, что это не очень хороший ответ, потому что можно утверждать, чтоx() && y() выглядит как следует оценить обе стороны выражения. Очевидно, что люди принимают это&& короткое замыкание, поэтому следует также&&= также. polygenelubricants
0

проверяет оба операнда, это 'побитовый оператор. Java определяет несколько побитовых операторов, которые могут применяться к целочисленным типам, long, int, short, char и byte. &&

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

&& Оператор похож на & оператор, но может сделать ваш код немного более эффективным. Поскольку оба выражения сравниваются&оператор должен бытьправдачтобы все выражение былоправда, естьнет смысла оценивать второе выражение, если первое возвращаетложный.& Оператор всегда оценивает оба выражения.&&Оператор оценивает второе выражение, только если первое выражение истинно.

Иметь &&= оператор присваивания не будетт действительно добавить новую функциональность к языку. Побитовый операторАрифметика гораздо более выразительна, вы можете делать целочисленную побитовую арифметику, которая включает в себя булеву арифметику Логические операторы могут просто выполнять булеву арифметику.

4

цели был чтобы быть "Простой, объектно-ориентированный и знакомый. " Применительно к этому делу, &= знакомо (C, C ++ имеет его и знакомо в этом контексте означает знакомое для тех, кто знает эти два). &&

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

24
причина

&&= а также||= не доступны наДжава потому что для большинства разработчиков эти операторы:

подверженные ошибкибесполезныйПример для&&=

Если 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(); гдеf2() вызывается только когдаf1() возвращается.true

Если разработчик хочетf2() быть вызванным только когдаf1() возвращаетсяtrueпоэтому второй код выше менее подвержен ошибкам.

еще&= достаточно, потому что разработчик хочет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 ...
На самом деле, я думаю, что я был не прав. StriplingWarrior
Спасибо @FranzB. за ваш отзыв: вы правы. Я буду обновлять ответ в ближайшее время (на данный момент не хватает времени, чтобы глубоко войти в эту тему) Приветствия ;-) olibre
Я нене согласен, когда вы говорите "И это не то, что мы хотим ". Если я напишуisOK &&= f2(); Я хотел бы, чтобы это было как короткое замыкание&& делает. Tor Klingberg
Что если я хочу сделать это очень быстро? &&= будет быстрее чем &=, если он существует, то вы должны использоватьif (a) a = b для скорости adventurerOK
0

ятно безобразно!

вряд ли рассмотрим&&= быть некрасивым asgs
Но тогда C / Java никогда не должен был быть красивым. EFraim
4

что синтаксис Java основан на C (или, по крайней мере, на семействе C), а в C все эти операторы присваивания компилируются в арифметические или побитовые инструкции сборки на одном регистре. Версия оператора присваивания позволяет избежать временных затрат и может привести к созданию более эффективного кода на ранних неоптимизирующих компиляторах. Логический оператор (как их называют в C) эквиваленты (&&= а также||=) неиметь такое очевидное соответствие отдельным инструкциям по сборке; они обычно расширяются до последовательности тестов и инструкций.

Интересно, что такие языки, как рубинделать есть || = и &&знак равно

Изменить: терминология отличается между Java и C

В терминологии С, && и || являются "логические операторы, s6.5.13-14 в ISO 9899: 1999. Только побитовые операторылогический» применительно к одному биту (логическое значение в Java); в C нет однобитового типа, и логические операторы там применяются ко всем скалярным типам. p00ya
Я полагаю, вы имеете в видуусловный операторы эквиваленты нене может быть такого очевидного соответствия. В терминологии JLS логические операторы:&| а также ;^&& а также|| являются условными операторами. polygenelubricants
2

& а также ''&& не совпадают с ''&& является сокращенной операцией, которая не будет выполняться, если первый операнд равен false, а ''& все равно будет делать это (работает как с числом, так и с логическим значением).

Я согласен с тем, что имеет больше смысла в существовании, но это не так уж плохо, если его там нет. Я предполагаю, что это не было там, потому что у C нет этого.

Действительно могуне думаю почему.

-1

 b - логическое выражение, которое возвращает логическое значение, а a & b - побитовое выражение, которое возвращает целое число (если a и b - целые числа).

как вы думаете, они одинаковы?

 б должен в отличие от && б всегда оценивать б. Daniel Brückner
a & b может быть boolean.a & Tom Hawtin - tackline

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