Що таке Java?: Оператор викликається і що він робить?


161

Я працюю з Java пару років, але до недавнього часу я не стикався з цією конструкцією:

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

Це, мабуть, дуже просте питання, але хтось може це пояснити? Як я її читаю? Я майже впевнений, що знаю, як це працює.

  • якщо isHereце правда, getHereCount()називається,
  • якщо isHereпомилковим getAwayCount()називається.

Правильно? Як називається ця конструкція?


2
Дивіться також stackoverflow.com/questions/795286/what-does-do-in-c щодо версії цього питання на C ++ (насправді задають саме вчора).
Майкл Майерс

2
Майте на увазі, що світ C / C ++ / Java досить рівномірно розділений між людьми, які вважають, що це некрасиво і заплутано, і уникатимуть його, як чуми, і людьми, які думають, що ви насправді не можете стверджувати, що знаєте C, C ++ або Java, якщо ви не може розпізнати його і використовувати його, не зупиняючись на роздумах.
Пол Томблін

3
Як правило, поганою формою в Java вважається її використання поза ясними та найпростішими випадками. Якщо ви виявите, що їх гніздите, ви виходите. З іншого боку, у культурі C, де швидкий та розумний код оцінюється вище ясності, він вважається прийнятним.
Yishai

17
answer_to_question = (розпізнати_оператор)? (Social_acceptance): (condescending_finger_wag)
Dan

Ви можете посилатися на цей ресурс для отримання додаткової інформації.
Шива

Відповіді:


189

Так, це скорочена форма

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

Його називають умовним оператором . Багато людей (помилково) називають це потрійним оператором , оскільки це єдиний потрійний (триаргументаційний) оператор на Java, C, C ++ і, мабуть, багатьох інших мовах. Але теоретично може бути інший потрійний оператор, тоді як може бути лише один умовний оператор .

Офіційна назва вказана в специфікації мови Java :

§15.25 Умовний оператор? :

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

Зауважте, що обидві гілки повинні вести до методів із поверненими значеннями:

Помилка часу компіляції для другого або третього виразу операнда є викликом методу void.

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

Отже, якщо doSomething()і doSomethingElse()недійсні методи, ви не можете стиснути це:

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

в це:

someBool ? doSomething() : doSomethingElse();

Прості слова:

booleanCondition ? executeThisPartIfBooleanConditionIsTrue : executeThisPartIfBooleanConditionIsFalse 

Я не розумію, що нижній робить це неправильно. Я вірю вам і всім. Мені це виглядає так само, як оригінал. Це тому, що вони просто викликають іншу функцію, яка може або не може повернути значення і дозволить запустити наступний набір коду?
Джоні

8
Я припускаю, що doSomething () і doSomethingElse () - недійсні методи. Останній біт специфікації говорить про те, що потрійний оператор повинен повернути значення, тому жоден з операндів не може бути недійсним методом.
Майкл Майєрс

Це говорить трохи більше, ніж це. Він говорить про те, що умовний оператор заборонений, коли з'являється метод NIDO COULD. Так, наприклад, такі твердження: VALID: Рядок x = (false)? "X": "Y"; НЕ ВІДМОВА: (помилково)? "X": "Y";
kenj0418

4
Не помилково називати це "потрійним оператором", так само як не помилково (у 2016 році) називати Обаму "президентом", хоча можливо, що в майбутньому будуть й інші президенти.
Dawood ibn Kareem

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, яка говорить про трьох «умовних операторів», але лише про одного «потрійного оператора»? Якщо ви хочете, щоб було зрозуміло, про якого оператора ви маєте на увазі, можливо, краще використовувати ім’я, яке використовує більшість людей. (Так, я знаю, що я з’являюся на вечірці саме тоді, коли господар миє останній посуд).
Dawood ibn Kareem

@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

Умовний оператор має три вирази операнда; ? з'являється між першим і другим виразами, і: з'являється між другим і третім виразами.

Перший вираз повинен мати тип булевого або булевого типу, або виникає помилка часу компіляції.



5

Не зовсім коректно, якщо бути точним:

  1. якщо isHere вірно, результат getHereCount () повертається
  2. otheriwse на результат з getAwayCount () буде повернуто

Те, що "повернулося", дуже важливо. Це означає, що методи повинні повернути значення, і це значення має бути десь призначено.

Крім того, це не зовсім синтаксично еквівалентно версії if-else. Наприклад:

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

Якщо зашифровано if-else, це завжди призведе до більше байт-коду.


Я вважаю, що javac може вільно генерувати той самий байт-код. Хоча ви праві, що є незрозумілі кутові випадки, коли вони не рівноцінні.
Том Хотін - тайклін

Так, звісно. Для мене справжня заслуга умовного оператора - приклад, який я наводив. Альтернативою є або: // задихатися !! String temp = str1; якщо (перевірити) temp + = str2; else temp + = str3; temp + = str4; темп повернення; або ручне кодування операції додавання StringBuilder. Перший страждає від серйозної проблеми ефективності, а другий - занадто багатослівний і є кропітким зусиллям без особливих вигод.
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

Ця конструкція називається « Теріальний оператор у галузі комп’ютерних наук та програмування».
А Вікіпедія пропонує таке пояснення:

В інформатиці потрійний оператор (іноді неправильно його називають третинним оператором) - це оператор, який приймає три аргументи. Аргументи та результат можуть бути різного типу. Багато мов програмування, що використовують синтаксис, подібний С, містять потрійний оператор?:, Який визначає умовне вираження.

Не тільки на Java, цей синтаксис доступний і в PHP, і в 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 за допомогою цього оператора Ternary для одного рядка оператора коду.
Наприклад:

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 ++ ish. Оператор двокрапки питання: (один маркер) відомий як оператор Елвіса.
Том Хотін - тайклін

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.

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 <Ніл не запропонував цього. Він просто використав це як простий приклад того, як написати пропозицію. Детальніше про архів списку розсилки монет проекту.
Том Хотін - тайклін

Я просто прочитав вступ до пропозиції, і ти маєш рацію. Це Стівен Коулборн з Джоди і "немає Java 7" слави.
erickson

1

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

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

що краще, ніж використовувати якщо, інакше, якщо, ще.


0

Це умовний оператор, і це більше, ніж просто стислий спосіб написання, якщо заяви.

Оскільки це вираз, який повертає значення, його можна використовувати як частину інших виразів.



0

Мені справді подобається цей оператор, але читача слід враховувати.

Ви завжди повинні врівноважувати компактність коду з часом, витраченим на його читання, і в тому, що він має деякі досить серйозні недоліки.

Перш за все, йдеться про справу оригіналу Аскера. Він просто провів годину, публікуючи про це і читаючи відповіді. Скільки часу знадобилося б авторові писати кожен?: Як би / то протягом усього його життя. Не годину, щоб бути впевненим.

По-друге, у мовах, подібних до С, ви звикли просто знати, що умовні умови - це перше, що в цьому рядку. Я помітив це, коли використовував Ruby і натрапив на лінії:

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

Якби я довго був користувачем Ruby, у мене, ймовірно, не виникло б проблем з цією лінією, але виходячи з C, коли ви бачите "callMethodWever" як перше в рядку, ви очікуєте його виконання. ?: Менш криптовалютний, але все ще досить незвичний, щоб відкинути читача.

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

Коли це справді завдання, що базується на булевих значеннях і значеннях, у мене з цим проблеми не виникає, але з цим легко можна зловживати.


0

Умовні вирази мають абсолютно інший стиль, без явного, якщо у висловлюванні.

Синтаксис: булевий вираз? вираз1: вираз2;

Результатом цього умовного виразу є

вираз1, якщо булева експресія є істинною;

інакше результат - вираження2.

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

Примітка: Символи? і: з'являються разом у умовному виразі. Вони утворюють умовний оператор і його також називають потрійним оператором, оскільки він використовує три операнди. Це єдиний потрійний оператор на Яві.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.