Co to jest Java?: Operator nazywa i co robi?

161

Pracuję z Javą od kilku lat, ale do niedawna nie spotkałem się z tą konstrukcją:

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

To chyba bardzo proste pytanie, ale czy ktoś może to wyjaśnić? Jak to przeczytać? Jestem prawie pewien, że wiem, jak to działa.

  • jeśli isHerejest prawdą, getHereCount()nazywa się,
  • jeśli isHerejest fałszywe, getAwayCount()jest wywoływane.

Poprawny? Jak nazywa się ta konstrukcja?

mainstringargs
źródło
2
Zobacz także stackoverflow.com/questions/795286/what-does-do-in-c, aby zapoznać się z wersją tego pytania w języku C ++ (właściwie zadaną wczoraj).
Michael Myers
2
Należy pamiętać, że świat C / C ++ / Java jest dość równo podzielony między ludzi, którzy uważają, że jest brzydki i zagmatwany i unikną tego jak zarazy, oraz ludzi, którzy myślą, że tak naprawdę nie możesz twierdzić, że znasz C, C ++ lub Javę, jeśli ty nie mogę go rozpoznać i użyć go bez zastanowienia.
Paul Tomblin
3
Ogólnie uważa się, że używanie go poza najjaśniejszymi i najprostszymi przypadkami jest złą formą w Javie. Jeśli stwierdzisz, że je gniazdujesz, jesteś daleko. Z drugiej strony, w kulturze C, gdzie szybki i sprytny kod jest ceniony ponad przejrzystość, jest on uznawany za akceptowalny.
Yishai
17
answer_to_question = (rozpoznać operatora)? (social_acceptance): (condescending_finger_wag)
Dan,
Możesz polecić ten zasób, aby uzyskać więcej informacji.
Shiva,

Odpowiedzi:

189

Tak, jest to skrócona forma

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

Nazywa się to operatorem warunkowym . Wiele osób (błędnie) nazywa to operatorem trójargumentowym , ponieważ jest to jedyny operator trójargumentowy (trójargumentowy) w Javie, C, C ++ i prawdopodobnie w wielu innych językach. Ale teoretycznie mógłby istnieć inny operator trójskładnikowy, podczas gdy może istnieć tylko jeden operator warunkowy .

Oficjalna nazwa jest podana w specyfikacji języka Java :

§15.25 Operator warunkowy? :

Operator warunkowy ? :używa wartości logicznej jednego wyrażenia, aby zdecydować, które z dwóch innych wyrażeń powinno zostać ocenione.

Zauważ, że obie gałęzie muszą prowadzić do metod zwracających wartości:

Jest to błąd czasu kompilacji dla drugiego lub trzeciego wyrażenia operandu będącego wywołaniem metody void.

W rzeczywistości, zgodnie z gramatyką wyrażeń wyrażeniowych ( §14.8 ), wyrażenie warunkowe nie może pojawiać się w jakimkolwiek kontekście, w którym mogłoby pojawić się wywołanie metody void.

Tak więc, jeśli doSomething()i doSomethingElse()są nieważne metody, nie można skompresować tak:

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

zaangażowany w to:

someBool ? doSomething() : doSomethingElse();

Proste słowa:

booleanCondition ? executeThisPartIfBooleanConditionIsTrue : executeThisPartIfBooleanConditionIsFalse 
Michael Myers
źródło
Nie rozumiem, co robi dolny, co jest złe. Wierzę tobie i wszystkim. Po prostu wygląda tak samo jak oryginał. Czy dzieje się tak dlatego, że po prostu wywołują inną funkcję, która może zwracać wartość lub nie i zezwalać na uruchomienie następnego zestawu kodu?
johnny
8
Zakładam, że metody doSomething () i doSomethingElse () to metody void. Ostatni fragment specyfikacji mówi, że operator trójskładnikowy musi zwracać wartość, więc żaden z operandów nie może być metodą void.
Michael Myers
Mówi trochę więcej niż to. Mówi, że operator warunkowy nie jest dozwolony, gdy metoda void MOŻE pojawić się. Na przykład następujące instrukcje: VALID: String x = (false)? „X”: „Y”; NIEPRAWIDŁOWE: (fałsz)? „X”: „Y”;
kenj0418
4
Nie jest błędne nazywanie go „operatorem trójskładnikowym”, tak jak nie jest błędne (w 2016 r.) Nazywanie Obamy „prezydentem”, choć niewykluczone, że w przyszłości będą inni prezydenci.
Dawood ibn Kareem
2
@DawoodibnKareem myślę Michael celowo zawarte thew italicisation dnia the ternary operator, i że to , co oznacza, że jest błędne, to nie ternary operatorjest błędne. Operator trójargumentowy oznacza, że, jak mówi Michael, jest jedynym, który z kolei może prowadzić jedną przyjąć nie może być żadnych innych operatorów trójskładnikowych, co jest, co mówi Michael jest błędne, a ja zgadzam się, że będzie mieć błędne założenie.
Ghoti and Chips
32

Inni odpowiedzieli na to w rozsądnym zakresie, ale często podając nazwę „operator trójskładnikowy”.

Będąc pedantem, chciałbym wyjaśnić, że nazwa operatora jest operatorem warunkowym lub „operatorem warunkowym?:”. Jest to operator trójskładnikowy (w tym, że ma trzy operandy) i jest obecnie jedynym operatorem trójskładnikowym w Javie.

Jednak specyfikacja jest dość jasna, że jej nazwa jest operatorem warunkowym lub „operatorem warunkowym?:”, Aby była absolutnie jednoznaczna. Myślę, że wyraźniej jest nazywać to tą nazwą, ponieważ wskazuje ona do pewnego stopnia zachowanie operatora (ocenianie warunku), a nie tylko liczbę operandów, które ma.

Jon Skeet
źródło
3
Ta odpowiedź jest technicznie poprawna. Jednakże, ponieważ istnieje tylko jeden operator trójskładnikowy, często jest on nazywany operatorem trójskładnikowym. Chociaż ta nazwa nie przekazuje pełnego znaczenia operatora, jest to nazwa, która utknęła. Jeśli wspomnisz nazwę „operator trójskładnikowy”, programiści wiedzą, o czym mówisz. Wspomniana specyfikacja odnosi się również do tego operatora jako „trójskładnikowego warunku”, co wydaje się bardziej pouczające. java.sun.com/docs/books/jls/third_edition/html/…
Gary
17
Po prostu uważam, że warto nazywać coś po jego nazwie. W szczególności, jeśli Java kiedykolwiek otrzyma inny operator trójskładnikowy, osoby używające terminu „operator warunkowy” nadal będą poprawne i jednoznaczne - w przeciwieństwie do osób, które mówią po prostu „operator trójskładnikowy”. Tak, wyrażenie „operator trójskładnikowy” utknęło - moja odpowiedź jest częścią próby „odklejenia” go, tak samo jak próbuję poprawić twierdzenie, że „obiekty są przekazywane przez odniesienie”.
Jon Skeet
1
Czy mogę skierować cię do tej strony Oracle, która mówi o trzech "operatorach warunkowych", ale tylko o jednym "operatorze trójskładnikowym"? Jeśli chcesz wyjaśnić, który operator masz na myśli, prawdopodobnie lepiej jest użyć nazwy, której używa większość ludzi. (Tak, wiem, że przychodzę na przyjęcie w chwili, gdy gospodarz zmywa ostatnie naczynia).
Dawood ibn Kareem
@DavidWallace: Używanie „operatora warunkowego?:” Jest lepsze, IMO - dokona edycji, aby to wyjaśnić. Ale myślę, że warto przekonać ludzi, aby używali rzeczywistej nazwy operatora, zamiast skupiać się na jednym aspekcie (ile ma operandów), który nie ma nic wspólnego z jego zachowaniem. (Często też tutoriale są mniej precyzyjne niż specyfikacja, która wywołuje &&operator warunkowy i oraz operator ||warunkowy lub, ale używa tylko „operatora warunkowego” dla ?:.
Jon Skeet
Nie wiem Jeśli ktoś powie mi „operator warunkowy”, nie będę pewien, co ma na myśli. Tam, skąd pochodzę (na drugim końcu świata od ciebie), ludzie po prostu tak tego nie nazywają. Jeśli mówią „operator trójskładnikowy” lub „operator zaczepu”, to rozumiem. Podziwiam Twoją ambicję, chęć zmiany sposobu, w jaki ludzie mówią. Jeśli ktoś może to zrobić, to ty. Ale nie pokładam zbytniej nadziei ani nie widzę sensu.
Dawood ibn Kareem
17

Zgodnie ze specyfikacją Sun Java , nazywa się to operatorem warunkowym. Patrz rozdział 15.25. Masz rację co do tego, co robi.

Operator warunkowy? : używa wartości logicznej jednego wyrażenia, aby zdecydować, które z dwóch innych wyrażeń powinno zostać ocenione.

Operator warunkowy jest syntaktycznie prawostronny (grupuje od prawej do lewej), tak więc a? B: c? D: e? F: g oznacza to samo co a? B: (c? D: (e? F :sol)).

ConditionalExpression:
        ConditionalOrExpression
        ConditionalOrExpression ? Expression : ConditionalExpression

Operator warunkowy ma trzy wyrażenia operandowe; ? pojawia się między pierwszym a drugim wyrażeniem, a: pojawia się między drugim a trzecim wyrażeniem.

Pierwsze wyrażenie musi być typu logicznego lub logicznego, w przeciwnym razie wystąpi błąd w czasie kompilacji.

JRL
źródło
5
int count = isHere ? getHereCount(index) : getAwayCount(index);

znaczy :

if (isHere) {
    count = getHereCount(index);
} else {
    count = getAwayCount(index);
}
Romain Linsolas
źródło
5

Nie do końca poprawne, żeby być precyzyjnym:

  1. jeśli isHere jest prawdziwe, wynik z getHereCount () jest zwracany
  2. otheriwse ten wynik z getAwayCount () jest zwrócony

To „zwrócone” jest bardzo ważne. Oznacza to, że metody muszą zwracać wartość i ta wartość musi być gdzieś przypisana.

Ponadto nie jest dokładnie odpowiednikiem składniowym wersji if-else. Na przykład:

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

Jeśli zakodowane za pomocą if-else zawsze da więcej kodu bajtowego.

RichN
źródło
Uważam, że javac może wygenerować ten sam kod bajtowy. Chociaż masz rację, że istnieją niejasne przypadki narożne, w których nie są one równoważne.
Tom Hawtin - tackline
Tak oczywiście. Dla mnie prawdziwą zaletą operatora warunkowego jest podany przeze mnie przykład. Alternatywą są: // sapanie !! String temp = str1; if (sprawdź) temp + = str2; w przeciwnym razie temp + = str3; temp + = str4; temp. powrotu; lub ręczne kodowanie operacji dołączania StringBuilder. Pierwsza z nich ma poważny problem z wydajnością, podczas gdy druga jest zbyt rozwlekła i jest żmudnym wysiłkiem bez większych korzyści.
RichN
4

Potrójny, warunkowy; pomidor, pomidor. To, co jest naprawdę cenne, to inicjalizacja zmiennych. Jeśli (tak jak ja) lubisz inicjować zmienne tam, gdzie są zdefiniowane, warunkowy operator trójskładnikowy (bo to oba) pozwala ci to zrobić w przypadkach, gdy istnieje warunek dotyczący ich wartości. Szczególnie godne uwagi w ostatnich dziedzinach, ale przydatne także w innych miejscach.

na przykład:

public class Foo {
    final double    value;

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

Bez tego operatora - pod jakąkolwiek nazwą - musiałbyś uczynić to pole niekońcowym lub napisać funkcję po prostu w celu jej zainicjowania. Właściwie to nie w porządku - nadal można go zainicjować za pomocą if / else, przynajmniej w Javie. Ale uważam, że to czystsze.

Carl Manaster
źródło
3

Konstrukcja ta nosi nazwę operatora trójskładnikowego w technikach informatyki i programowania.
I Wikipedia sugerują następujące wyjaśnienie:

W informatyce operator trójskładnikowy (czasami błędnie nazywany operatorem trzeciorzędnym) to operator, który przyjmuje trzy argumenty. Argumenty i wynik mogą być różnych typów. Wiele języków programowania używających składni podobnej do języka C zawiera operator trójskładnikowy,?:, Który definiuje wyrażenie warunkowe.

Nie tylko w Javie, ta składnia jest dostępna również w PHP, Objective-C.

W poniższym linku podaje następujące wyjaśnienie, które jest ciche, dobrze je zrozumieć:

Operator trójskładnikowy to operacja działająca na 3 wejściach. Jest to skrót do instrukcji if-else i jest również nazywany operatorem warunkowym.

W Perl / PHP działa jako:
boolean_condition ? true_value : false_value

W C / C ++ działa jak:
logical expression ? action for true : action for false

Może to być czytelne dla niektórych warunków logicznych, które nie są zbyt złożone, w przeciwnym razie lepiej jest użyć bloku Jeśli- Inaczej z zamierzoną kombinacją logiki warunkowej.

Możemy uprościć bloki If-Else za pomocą tego operatora trójskładnikowego dla jednej linii instrukcji kodu.
Na przykład:

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

Może być równe następującym:

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

Więc jeśli odnosimy się do twojego oświadczenia:

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

W rzeczywistości jest to 100% odpowiednik następującego bloku Jeśli-Inaczej :

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

Otóż ​​to!
Mam nadzieję, że to komuś pomogło!
Twoje zdrowie!

Randika Vishman
źródło
2

Poprawny. To nazywa operator trójskładnikowych . Niektórzy nazywają to również operatorem warunkowym .

cletus
źródło
9
Cytując Alicję w Krainie Czarów, nazywa się to operatorem trójskładnikowym, ale jego nazwą jest operator warunkowy.
Paul Tomblin
Ale jego nazwa nazywa się operatorem dwukropka znaku zapytania.
Michael Myers
1
Nazewnictwo nazewnictwa brzmi trochę C ++ ish. Operator dwukropka znaku zapytania?: (Jeden token) jest znany jako operator Elvisa.
Tom Hawtin - tackline
2

Jego operator trójskładnikowy (? :)

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
źródło
1

Możesz być zainteresowany propozycją nowych operatorów, które są podobne do operatora warunkowego. Operatory o wartości null-safe włączą następujący kod:

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

Byłoby to szczególnie wygodne w przypadku automatycznego rozpakowywania.

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

Został wybrany do dalszych rozważań w ramach projektu „Moneta projektu” JDK 7.

erickson
źródło
Ten operator nie jest jednym z moich ulubionych z Project Coin. Ograniczona użyteczność, nie intuicyjna do czytania i po prostu brzydka jak wszystko. Może jednak wzrośnie na mnie.
Michael Myers
Właściwie nie jestem też wielkim fanem. To propozycja Neala Gaftera i on ma tendencję do postrzegania rzeczy zupełnie inaczej niż przeciętny programista Java, który ma tendencję do postrzegania rzeczy inaczej niż przeciętny człowiek. Jedyne miejsca, w których mogłabym potrzebować niewielkiej pomocy z wartościami null, to pętla foreach, sprawdzanie, czy iterowalność jest pusta, i automatyczne rozpakowywanie.
erickson
IIRC <Neal tego nie zaproponował. Użył go tylko jako prostego przykładu, jak napisać propozycję. Więcej szczegółów w archiwum listy mailingowej projektu coin.
Tom Hawtin - tackline
Właśnie przeczytałem wprowadzenie do propozycji i masz rację. To Stephen Colebourne z Joda i sława „nie ma Javy 7”.
erickson
1

W rzeczywistości może to zająć więcej niż 3 argumenty. Na przykład, jeśli chcemy sprawdzić, czy liczba jest dodatnia, ujemna czy zero, możemy to zrobić:

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

co jest lepsze niż używanie if, else if, else.

Chwalony
źródło
0

Jest to operator warunkowy i jest czymś więcej niż zwięzłym sposobem pisania instrukcji if.

Ponieważ jest to wyrażenie zwracające wartość, może być używane jako część innych wyrażeń.

justinhj
źródło
0

Tak, masz rację. ?: jest zwykle nazywany „trójskładnikowym operatorem warunkowym”, często nazywany po prostu „trójskładnikowym operatorem”. Jest to skrócona wersja standardu warunkowego if / else.

Operator warunkowy trójskładnikowy

Gary
źródło
0

Tak się składa, że ​​bardzo lubię ten operator, ale czytelnik powinien być wzięty pod uwagę.

Zawsze musisz zrównoważyć zwartość kodu z czasem spędzonym na jego czytaniu, ponieważ ma on kilka poważnych wad.

Przede wszystkim jest to sprawa Original Asker. Po prostu spędził godzinę, pisząc o tym i czytając odpowiedzi. Ile czasu zajęłoby autorowi pisanie każdego?: Jako „jeśli / wtedy” przez całe życie. Nie ma godziny, żeby mieć pewność.

Po drugie, w językach typu C masz zwyczaj po prostu wiedzieć, że warunki warunkowe są pierwszą rzeczą w linii. Zauważyłem to, gdy używałem Rubiego i napotkałem linie takie jak:

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

Gdybym był użytkownikiem Rubiego przez długi czas, prawdopodobnie nie miałbym problemu z tą linią, ale wychodząc z C, kiedy widzisz "callMethodWhthing" jako pierwszą rzecz w linii, spodziewasz się, że zostanie wykonana. ?: Jest mniej tajemniczy, ale wciąż na tyle niezwykły, że może zrzucić czytelnika.

Zaletą jest jednak naprawdę fajne uczucie w brzuszku, kiedy możesz napisać 3-liniowe zdanie if w przestrzeni 1 z nich. Nie można temu zaprzeczyć :) Ale szczerze, niekoniecznie bardziej czytelne dla 90% ludzi po prostu ze względu na jego rzadkość.

Kiedy jest to naprawdę zadanie oparte na wartości logicznej i wartościach, nie mam z tym problemu, ale można je łatwo nadużyć.

Bill K.
źródło
0

Wyrażenia warunkowe mają zupełnie inny styl, bez wyraźnego wyrażenia if w instrukcji.

Składnia to: wyrażenie-boolowskie? wyrażenie1: wyrażenie2;

Wynikiem tego wyrażenia warunkowego jest

wyrażenie1, jeśli wyrażenie-boolowskie jest prawdziwe;

w przeciwnym razie wynik to wyrażenie2.

Załóżmy, że chcesz przypisać większą liczbę zmiennych num1 i num2 do max. Możesz po prostu napisać instrukcję, używając wyrażenia warunkowego: max = (num1> num2)? num1: num2;

Uwaga: symbole? i: pojawiają się razem w wyrażeniu warunkowym. Tworzą operator warunkowy, zwany także operatorem trójskładnikowym, ponieważ używa trzech operandów. Jest to jedyny operator trójskładnikowy w Javie.

cytowane z: Intro to Java Programming 10. wydanie autorstwa Y. Daniel Liang str. 126 - 127

Ged
źródło