Как называется оператор Java?: И что он делает?

161

Я работал с Java пару лет, но до недавнего времени я не сталкивался с этой конструкцией:

int count = isHere ? getHereCount(index) : getAwayCount(index);

Вероятно, это очень простой вопрос, но кто-нибудь может это объяснить? Как мне это прочитать? Я уверен, что знаю, как это работает.

  • если isHereэто правда, getHereCount()называется,
  • если isHereложь getAwayCount()называется.

Верный? Как называется эта конструкция?

mainstringargs
источник
2
См. Также stackoverflow.com/questions/795286/what-does-do-in-c для версии C ++ этого вопроса (фактически задаваемого только вчера).
Майкл Майерс
2
Имейте в виду, что мир C / C ++ / Java довольно равномерно разделен между людьми, которые считают его уродливым и запутанным и избегут его, как чума, и людьми, которые думают, что вы не можете утверждать, что знаете C, C ++ или Java, если вы не могу распознать и использовать его, не задумываясь.
Пол Томблин
3
Обычно считается плохой формой использования Java за пределами самых ясных и простых случаев. Если вы обнаружите, что вкладываете их, вы выходите. С другой стороны, в культуре Си, где быстрый и умный код оценивается выше ясности, он считается приемлемым.
Ишай
17
answer_to_question = (распознавать_оператор)? (social_acceptance): (condescending_finger_wag)
Дан,
Вы можете обратиться к этому ресурсу для получения дополнительной информации.
Шива

Ответы:

189

Да, это сокращенная форма

int count;
if (isHere)
    count = getHereCount(index);
else
    count = getAwayCount(index);

Это называется условный оператор . Многие (ошибочно) называют его троичным оператором , потому что это единственный троичный оператор (с тремя аргументами) в Java, C, C ++ и, возможно, во многих других языках. Но теоретически может быть другой троичный оператор, тогда как может быть только один условный оператор .

Официальное название дано в Спецификации языка Java :

§15.25 Условный оператор? :

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

Обратите внимание, что обе ветви должны приводить к методам с возвращаемыми значениями:

Это ошибка времени компиляции, поскольку второе или третье выражение операнда является вызовом метода void.

На самом деле, согласно грамматике операторов выражений ( §14.8 ), условное выражение не допускается в любом контексте, где может возникнуть вызов метода void.

Итак, если doSomething()и doSomethingElse()являются пустыми методами, вы не можете сжать это:

if (someBool)
    doSomething();
else
    doSomethingElse();

в это:

someBool ? doSomething() : doSomethingElse();

Простые слова:

booleanCondition ? executeThisPartIfBooleanConditionIsTrue : executeThisPartIfBooleanConditionIsFalse 
Майкл Майерс
источник
Я не понимаю, что делает нижний, это неправильно. Я верю тебе и всем. Это выглядит так же, как оригинал. Это потому, что они просто вызывают другую функцию, которая может возвращать или не возвращать значение и разрешать запуск следующего набора кода?
Джонни
8
Я предполагаю, что doSomething () и doSomethingElse () являются пустыми методами. Последний бит спецификации говорит о том, что троичный оператор должен возвращать значение, поэтому ни один из операндов не может быть пустым методом.
Майкл Майерс
Это говорит немного больше, чем это. В нем говорится, что условный оператор недопустим там, где может появиться пустой метод. Так, например, следующие операторы: VALID: String x = (false)? "X": "Y"; НЕ ДЕЙСТВИТЕЛЬНО: (неверно)? "X": "Y";
kenj0418
4
Нельзя ошибочно называть его «троичным оператором», так же как не ошибочно (в 2016 году) называть Обаму «президентом», хотя вполне возможно, что в будущем появятся другие президенты.
Дауд ибн Карим
2
@DawoodibnKareem Я думаю, что Майкл сознательно включен theв курсив the ternary operator, и это означает , что он ошибочен, а не ternary operatorошибочен. Троичный оператор предполагает , что, как говорит Майкл, это только один, который , в свою очередь , может привести к предположению , что не может быть никаких других тройные операторов, является то , что Майкл говорит , является ошибочным, и я согласен, это было бы ошибочное предположение.
Ghoti and Chips
32

Другие ответили на это в разумной степени, но часто с названием «троичный оператор».

Будучи педантом, которым я являюсь, я хотел бы прояснить, что имя оператора - это условный оператор или «условный оператор?». Это троичный оператор (в том , что он имеет три операнда) , и это случается только тройной оператор в Java на данный момент.

Тем не менее, спецификация довольно ясно, что ее имя является условным оператором или «условным оператором?», Чтобы быть абсолютно однозначным. Я думаю, что более понятно называть его этим именем, поскольку оно указывает на поведение оператора в некоторой степени (оценивает условие), а не просто на то, сколько у него операндов.

Джон Скит
источник
3
Этот ответ технически правильный. Однако, поскольку существует только один троичный оператор, его часто называют троичным оператором. Хотя это имя не передает полное значение оператора, это имя застряло. Если вы упомянули имя «троичный оператор», программисты знают, о чем вы говорите. Спецификация, которую вы упоминаете, также ссылается на этот оператор как «троичное условие», которое кажется более информативным. java.sun.com/docs/books/jls/third_edition/html/…
Гари
17
Я просто думаю, что стоит назвать что-то по определенному имени. В частности, если Java когда-либо получит еще один троичный оператор, люди, которые используют термин «условный оператор», все равно будут правильными и однозначными - в отличие от тех, кто просто говорит «троичный оператор». Да, фраза «троичный оператор» застряла - мой ответ является частью попытки «открепить» ее, так же как я пытаюсь исправить утверждение, что «объекты передаются по ссылке».
Джон Скит
1
Могу ли я направить вас на эту страницу из Oracle, где говорится о трех «условных операторах», но только об одном «тройном операторе»? Если вы хотите прояснить, какого оператора вы имеете в виду, вероятно, лучше использовать имя, которое используют большинство людей. (Да, я знаю, что я появляюсь на вечеринке, когда ведущий моет последние блюда).
Дауд ибн Карим
@DavidWallace: лучше использовать «условный оператор?:», IMO - отредактирую, чтобы уточнить это. Но я думаю, что стоит убедить людей использовать фактическое имя оператора, а не фокусироваться на одном его аспекте (сколько у него операндов), который не имеет никакого отношения к его поведению. (Также нередко учебники менее точны, чем спецификация, которая вызывает &&оператор условного оператора и оператор ||условного оператора или, но использует только «условный оператор» для ?:.
Джон Скит
Я не знаю. Если кто-то скажет мне «условный оператор», я не буду уверен, что они имеют в виду. Откуда я родом (противоположный конец света от вас) люди просто не называют это так. Если они говорят «троичный оператор» или «оператор крючка», то я понимаю. Я восхищаюсь твоими амбициями, желая изменить то, как люди разговаривают. Если кто-то может сделать это, это ты. Но я не надеюсь и не вижу особого смысла.
Дауд ибн Карим
17

Согласно спецификации Sun Java , он называется условным оператором. Смотрите раздел 15.25. Вы правы относительно того, что он делает.

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

Условный оператор синтаксически справа ассоциативен (он группируется справа налево), так что a? B: c? D: e? F: g означает то же самое, что и a b: (c? D: (e? F) :грамм)).

ConditionalExpression:
        ConditionalOrExpression
        ConditionalOrExpression ? Expression : ConditionalExpression

Условный оператор имеет три выражения операнда; ? появляется между первым и вторым выражениями, а: появляется между вторым и третьим выражениями.

Первое выражение должно иметь тип boolean или Boolean, иначе произойдет ошибка времени компиляции.

JRL
источник
5
int count = isHere ? getHereCount(index) : getAwayCount(index);

средства :

if (isHere) {
    count = getHereCount(index);
} else {
    count = getAwayCount(index);
}
Ромэн Линсолас
источник
5

Не совсем правильно, если быть точным:

  1. если isHere - true, возвращается результат getHereCount ()
  2. otheriwse на результат из getAwayCount () будет возвращено

Это «вернулся» очень важно. Это означает, что методы должны возвращать значение, и это значение должно быть где-то назначено.

Кроме того, это не совсем синтаксически эквивалентно версии if-else. Например:

String str1,str2,str3,str4;
boolean check;
//...
return str1 + (check ? str2 : str3) + str4;

Если закодировано с помощью if-else, всегда будет получаться больше байт-кода.

RichN
источник
Я считаю, что javac может генерировать один и тот же байт-код. Хотя вы правы, что есть неясные угловые случаи, когда они не эквивалентны.
Том Хотин - tackline
Ну конечно; естественно. Для меня истинная заслуга условного оператора - это пример, который я привел. Альтернатива: // вздох !! Строка temp = str1; if (отметьте) temp + = str2; иначе temp + = str3; temp + = str4; вернуть темп; или ручное кодирование операции добавления StringBuilder. 1-й страдает от серьезной проблемы с эффективностью, в то время как 2-й слишком многословен и является кропотливым усилием без особой выгоды.
RichN
4

Тройной, условный; помидор, томат. Для чего это действительно ценно - это инициализация переменных. Если (как и я) вам нравится инициализировать переменные там, где они определены, то условный троичный оператор (для него обоих) позволяет вам делать это в тех случаях, когда существует условие относительно его значения. Особенно примечателен в финальных полях, но полезен и в других местах.

например:

public class Foo {
    final double    value;

    public Foo(boolean positive, double value) {
        this.value = positive ? value : -value;
    }
}

Без этого оператора - по какому-либо имени - вам пришлось бы сделать поле не финальным или написать функцию просто для его инициализации. На самом деле, это не так - его все еще можно инициализировать, используя if / else, по крайней мере, в Java. Но я нахожу это чище.

Карл Манастер
источник
4
condition ? truth : false;

Если условие выполняется, trueвычислите первое выражение. Если условиеfalse , оцените второе выражение.

Он называется условным оператором и является типом троичной операции .

Джо Филлипс
источник
1
Согласно JLS, 15,25. Условный оператор? : это оценка, а не «возврат» и выражение, а не «параметр».
Герольд Брозер
3

Эта конструкция называется троичным оператором в области компьютерных наук и методов программирования.
И Википедия предлагает следующее объяснение:

В информатике троичный оператор (иногда неправильно называемый третичным оператором) - это оператор, который принимает три аргумента. Аргументы и результат могут быть разных типов. Многие языки программирования, использующие C-подобный синтаксис, имеют троичный оператор?:, Который определяет условное выражение.

Этот синтаксис доступен не только в Java, но и в Objective-C.

В следующей ссылке приведено следующее объяснение, которое приятно понять:

Тернарный оператор - это некоторая операция, работающая на 3 входах. Это сокращение для оператора if-else, также известное как условный оператор.

В Perl / PHP это работает так:
boolean_condition ? true_value : false_value

В C / C ++ это работает так:
logical expression ? action for true : action for false

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

С помощью этого тернарного оператора мы можем упростить блоки If-Else для одной строки оператора кода.
Например:

if ( car.isStarted() ) {
     car.goForward();
} else {
     car.startTheEngine();
}

Может быть равным следующему:

( car.isStarted() ) ? car.goForward() : car.startTheEngine();

Итак, если мы ссылаемся на ваше заявление:

int count = isHere ? getHereCount(index) : getAwayCount(index);

На самом деле это 100% эквивалент следующего блока If-Else :

int count;
if (isHere) {
    count = getHereCount(index);
} else {
    count = getAwayCount(index);
}

Это оно!
Надеюсь, это было полезно для кого-то!
Ура!

Рандика Вишман
источник
2

Верный. Это называется троичным оператором . Некоторые также называют это условным оператором .

Клетус
источник
9
Цитируя Алису в стране чудес, она называется троичным оператором, но его имя - условный оператор.
Пол Томблин
Но имя его называется оператор двоеточия вопросительного знака.
Майкл Майерс
1
Называние именования звучит немного в C ++. Оператор двоеточия вопросительного знака?: (Один токен) известен как оператор Элвиса.
Том Хотин - tackline
2

Его троичный оператор (? :)

The ternary operator is an operator that takes three arguments. The first 
argument is a comparison argument, the second is the result upon a true 
comparison, and the third is the result upon a false comparison.
Darsy
источник
1

Возможно, вас заинтересует предложение о некоторых новых операторах, похожих на условный оператор. Нуль-безопасные операторы включат код следующим образом:

String s = mayBeNull?.toString() ?: "null";

Было бы особенно удобно, когда происходит автоматическая распаковка.

Integer ival = ...;  // may be null
int i = ival ?: -1;  // no NPE from unboxing

Он был выбран для дальнейшего рассмотрения в рамках проекта JDK 7 «Монета проекта».

Эриксон
источник
Этот оператор не один из моих любимых в Project Coin. Ограниченная полезность, не интуитивно понятный и просто уродливый, как у всех. Может быть, это будет расти на меня, хотя.
Майкл Майерс
Вообще-то, я не большой поклонник. Это предложение Нила Гафтера, и он склонен видеть вещи совсем иначе, чем ваш обычный Java-программист, который склонен смотреть на вещи иначе, чем ваш обычный человек. Единственные места, где мне может понадобиться небольшая помощь по нулям, - это цикл foreach, проверка, является ли итерируемое значение null, и автоматическая распаковка.
erickson
IIRC <Нил не предлагал это. Он просто использовал это как простой пример того, как написать предложение. Подробнее о архиве списка рассылки проекта.
Том Хотин - tackline
Я только что прочитал вступление к предложению, и вы правы. Это Стивен Коулбурн из Joda и слава "нет Java 7".
Эриксон,
1

На самом деле это может занять более 3 аргументов. Например, если мы хотим проверить, является ли число положительным, отрицательным или нулевым, мы можем сделать это:

String m= num > 0 ? "is a POSITIVE NUMBER.": num < 0 ?"is a NEGATIVE NUMBER." :"IT's ZERO.";

что лучше, чем использование if, else if, else.

Благословен
источник
0

Это условный оператор, и это больше, чем просто краткий способ написания операторов if.

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

justinhj
источник
0

Да вы правы. ?: обычно называется «троичным условным оператором», часто называемым просто «троичным оператором». Это сокращенная версия стандарта if / else условная.

Тернарный условный оператор

Gary
источник
0

Мне очень нравится этот оператор, но читатель должен быть принят во внимание.

Вы всегда должны уравновешивать компактность кода со временем, потраченным на его чтение, и в этом есть некоторые довольно серьезные недостатки.

Прежде всего, это дело Первоначального Аскера. Он просто час писал об этом и читал ответы. Сколько времени понадобилось бы автору, чтобы написать каждый? Как если бы / то на протяжении всей его жизни. Не час, чтобы быть уверенным.

Во-вторых, в C-подобных языках вы привыкли просто знать, что условные выражения - это первое, что есть в строке. Я заметил это, когда использовал Ruby и наткнулся на такие строки:

callMethodWhatever(Long + Expression + with + syntax) if conditional

Если бы я долгое время был пользователем Ruby, у меня, вероятно, не было бы проблемы с этой строкой, но, если исходить из C, когда вы видите в качестве первой в строке «callMethodWhwhat», вы ожидаете, что она будет выполнена. ?: Менее загадочный, но все же достаточно необычный, чтобы отбросить читателя.

Преимущество, однако, в том, что вы можете написать 3-строчный оператор if в интервале 1 из строк. Не могу этого отрицать :) Но, честно говоря, не обязательно более читабельно 90% людей там просто из-за его редкости.

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

Билл К
источник
0

Условные выражения выполняются в совершенно другом стиле, без явного выражения if.

Синтаксис: логическое выражение? выражение1: выражение2;

Результатом этого условного выражения является

expression1, если логическое выражение имеет значение true;

в противном случае результатом является выражение2.

Предположим, вы хотите присвоить большее количество переменных num1 и num2 максимальному значению. Вы можете просто написать оператор, используя условное выражение: max = (num1> num2)? число1: число2;

Примечание: символы? и: появляются вместе в условном выражении. Они образуют условный оператор и также называются троичным оператором, потому что он использует три операнда. Это единственный троичный оператор в Java.

цитируется с: Введение в программирование на Java, 10-е издание, Y. Daniel Liang стр. 126 - 127

Гед
источник