Wie heißt der Operator Java ?: Und was macht er?


161

Ich habe ein paar Jahre mit Java gearbeitet, aber bis vor kurzem bin ich nicht auf dieses Konstrukt gestoßen:

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

Dies ist wahrscheinlich eine sehr einfache Frage, aber kann jemand sie erklären? Wie lese ich es? Ich bin mir ziemlich sicher, dass ich weiß, wie es funktioniert.

  • wenn isHerees wahr getHereCount()ist, heißt es
  • wenn isHerefalsch getAwayCount()ist, wird aufgerufen.

Richtig? Wie heißt dieses Konstrukt?


2
Siehe auch stackoverflow.com/questions/795286/what-does-do-in-c für die C ++ - Version dieser Frage (tatsächlich erst gestern gestellt).
Michael Myers

2
Denken Sie daran, dass die C / C ++ / Java-Welt ziemlich gleichmäßig zwischen Menschen aufgeteilt ist, die es für hässlich und verwirrend halten und es wie die Pest vermeiden, und Menschen, die glauben, Sie könnten nicht wirklich behaupten, C, C ++ oder Java zu kennen, wenn Sie dies tun kann es nicht erkennen und benutzen, ohne nachzudenken.
Paul Tomblin

3
In Java wird es allgemein als schlechte Form angesehen, sie über die klarsten und einfachsten Fälle hinaus zu verwenden. Wenn Sie feststellen, dass Sie sie verschachteln, sind Sie ein Ausweg. Andererseits wird in der C-Kultur, in der schneller und cleverer Code über Klarheit steht, dies als akzeptabel angesehen.
Yishai

17
answer_to_question = (Erkennungsoperator)? (social_acceptance): (herablassend_finger_wag)
Dan

Weitere Informationen finden Sie in dieser Ressource.
Shiva

Antworten:


189

Ja, es ist eine Kurzform von

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

Es heißt der bedingte Operator . Viele Leute nennen es (fälschlicherweise) den ternären Operator , weil es der einzige ternäre Operator (mit drei Argumenten) in Java, C, C ++ und wahrscheinlich vielen anderen Sprachen ist. Theoretisch könnte es jedoch einen anderen ternären Operator geben, während es nur einen bedingten Operator geben kann .

Der offizielle Name ist in der Java-Sprachspezifikation angegeben :

§15.25 Bedingter Operator? ::

Der bedingte Operator ? :verwendet den booleschen Wert eines Ausdrucks, um zu entscheiden, welcher von zwei anderen Ausdrücken ausgewertet werden soll.

Beachten Sie, dass beide Zweige zu Methoden mit Rückgabewerten führen müssen:

Es ist ein Fehler zur Kompilierungszeit, wenn entweder der zweite oder der dritte Operandenausdruck ein Aufruf einer void-Methode ist.

Tatsächlich ist es nach der Grammatik der Ausdrucksanweisungen ( § 14.8 ) nicht zulässig, dass ein bedingter Ausdruck in einem Kontext erscheint, in dem ein Aufruf einer void-Methode auftreten könnte.

Wenn also doSomething()und doSomethingElse()void Methoden sind, können Sie dies nicht komprimieren:

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

das mögen:

someBool ? doSomething() : doSomethingElse();

Einfache Worte:

booleanCondition ? executeThisPartIfBooleanConditionIsTrue : executeThisPartIfBooleanConditionIsFalse 

Ich verstehe nicht, was der unterste tut, das ist falsch. Ich glaube dir und allen. Es sieht für mich genauso aus wie das Original. Liegt es daran, dass sie nur eine andere Funktion aufrufen, die möglicherweise einen Wert zurückgibt oder nicht, und die Ausführung des nächsten Codesatzes zulassen?
Johnny

8
Ich gehe davon aus, dass doSomething () und doSomethingElse () nichtige Methoden sind. Was das letzte Bit der Spezifikation sagt, dass der ternäre Operator muss einen Wert zurückgeben, so dass keiner der Operanden kann Leere Methoden sein.
Michael Myers

Es sagt ein bisschen mehr als das. Es heißt, dass der bedingte Operator nicht zulässig ist, wenn eine ungültige Methode angezeigt werden KÖNNTE. Also zum Beispiel die folgenden Anweisungen: VALID: String x = (false)? "X": "Y"; NICHT GÜLTIG: (falsch)? "X": "Y";
Kenj0418

4
Es ist nicht falsch, es als "ternären Operator" zu bezeichnen, genauso wie es nicht falsch ist (2016), Obama als "den Präsidenten" zu bezeichnen, obwohl es möglich ist, dass es in Zukunft andere Präsidenten geben wird.
Dawood ibn Kareem

2
@DawoodibnKareem Ich denke, Michael hat absichtlich thein die Kursivschrift von einbezogen the ternary operator, und das, was er meint, ist falsch, nicht das ternary operatorist falsch. Der ternäre Operator impliziert, dass es, wie Michael sagt, der einzige ist, der wiederum zu der Annahme führen könnte, dass es keine anderen ternären Operatoren geben kann, was Michael als falsch bezeichnet, und ich würde zustimmen, dass dies der Fall ist eine falsche Annahme.
Ghoti und Chips

32

Andere haben dies in angemessenem Umfang beantwortet, jedoch häufig mit dem Namen "ternärer Operator".

Als der Pedant, der ich bin, möchte ich klarstellen, dass der Name des Operators der bedingte Operator oder "bedingter Operator ?:" Ist. Es ist ein ternärer Operator (da er drei Operanden hat) und derzeit der einzige ternäre Operator in Java.

Die Spezifikation ist jedoch ziemlich klar, dass ihr Name der bedingte Operator oder "bedingte Operator ?:" Ist, um absolut eindeutig zu sein. Ich denke, es ist klarer, es bei diesem Namen zu nennen, da es das Verhalten des Operators in gewissem Maße anzeigt (Bewertung einer Bedingung) und nicht nur die Anzahl der Operanden.


3
Diese Antwort ist technisch korrekt. Da es jedoch nur einen ternären Operator gibt, wird dieser häufig als ternärer Operator bezeichnet. Obwohl dieser Name nicht die vollständige Bedeutung des Operators wiedergibt, ist er ein Name, der stecken geblieben ist. Wenn Sie den Namen "ternärer Operator" erwähnen, wissen Programmierer, wovon Sie sprechen. Die von Ihnen erwähnte Spezifikation bezieht sich auch auf diesen Operator als "Ternäre Bedingung", was informativer erscheint. java.sun.com/docs/books/jls/third_edition/html/…
Gary

17
Ich denke nur, dass es sich lohnt, etwas beim definierten Namen zu nennen. Insbesondere wenn Java jemals einen anderen ternären Operator erhält, sind Personen, die den Begriff "bedingter Operator" verwenden, immer noch korrekt und eindeutig - im Gegensatz zu denen, die nur "ternärer Operator" sagen. Ja, der Ausdruck "ternärer Operator" ist geblieben - meine Antwort ist Teil der Bemühungen, ihn zu "lösen", genau wie ich versuche, die Behauptung zu korrigieren, dass "Objekte als Referenz übergeben werden".
Jon Skeet

1
Darf ich Sie auf diese Seite von Oracle verweisen, die von drei "bedingten Operatoren", aber nur einem "ternären Operator" spricht? Wenn Sie klarstellen möchten, welchen Operator Sie meinen, ist es wahrscheinlich besser, den Namen zu verwenden, den die meisten Leute verwenden. (Ja, ich weiß, dass ich gerade auf der Party auftauche, als der Gastgeber das letzte Geschirr spült).
Dawood ibn Kareem

@DavidWallace: Die Verwendung von "Bedingter Operator ?:" Ist besser, IMO - wird bearbeitet, um dies zu verdeutlichen. Ich denke jedoch, dass es sich lohnt, die Leute davon zu überzeugen, den tatsächlichen Namen des Operators zu verwenden, anstatt sich auf einen Aspekt (wie viele Operanden) zu konzentrieren, der nichts mit seinem Verhalten zu tun hat. (Es ist auch nicht ungewöhnlich, dass Tutorials weniger genau sind als die Spezifikation, die &&den Bedingungs- und Operator und ||den Bedingungs- oder Operator aufruft , sondern nur "den bedingten Operator" für ?:.
Jon Skeet

Ich weiß es nicht. Wenn jemand zu mir "bedingter Operator" sagt, bin ich mir nicht sicher, was er bedeutet. Woher ich komme (das andere Ende der Welt von dir), nennen die Leute es einfach nicht so. Wenn sie "ternärer Operator" oder "Hook-Operator" sagen, dann verstehe ich. Ich bewundere Ihren Ehrgeiz und möchte die Art und Weise ändern, wie Menschen sprechen. Wenn jemand es kann, bist du es. Aber ich habe weder viel Hoffnung noch sehe ich viel Sinn.
Dawood ibn Kareem

17

Gemäß der Sun Java-Spezifikation wird sie als bedingter Operator bezeichnet. Siehe Abschnitt 15.25. Sie haben Recht, was es tut.

Der bedingte Operator? : verwendet den booleschen Wert eines Ausdrucks, um zu entscheiden, welcher von zwei anderen Ausdrücken ausgewertet werden soll.

Der bedingte Operator ist syntaktisch rechtsassoziativ (er gruppiert von rechts nach links), so dass a? B: c? D: e? F: g dasselbe bedeutet wie a? B: (c? D: (e? F.) :G)).

ConditionalExpression:
        ConditionalOrExpression
        ConditionalOrExpression ? Expression : ConditionalExpression

Der bedingte Operator hat drei Operandenausdrücke. ? erscheint zwischen dem ersten und dem zweiten Ausdruck und: erscheint zwischen dem zweiten und dritten Ausdruck.

Der erste Ausdruck muss vom Typ Boolean oder Boolean sein, da sonst ein Fehler bei der Kompilierung auftritt.


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

meint :

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

5

Nicht genau richtig, um genau zu sein:

  1. Wenn isHere true ist, wird das Ergebnis von getHereCount () zurückgegeben
  2. Andernfalls wird das Ergebnis von getAwayCount () zurückgegeben

Diese "Rückkehr" ist sehr wichtig. Es bedeutet , dass die Methoden müssen einen Wert zurückgeben und dieser Wert muss irgendwo zugeordnet werden.

Außerdem entspricht es nicht genau der if-else-Version. Beispielsweise:

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

Wenn mit if-else codiert, wird immer mehr Bytecode erstellt.


Ich glaube, es steht Javac frei, denselben Bytecode zu generieren. Obwohl Sie richtig sind, dass es dunkle Eckfälle gibt, in denen sie nicht gleichwertig sind.
Tom Hawtin - Tackline

Ja natürlich. Für mich ist das wahre Verdienst des bedingten Operators das Beispiel, das ich gegeben habe. Die Alternative sind entweder: // keuchen !! String temp = str1; if (check) temp + = str2; sonst temp + = str3; temp + = str4; Rücklauftemperatur; oder Handcodierung der StringBuilder-Append-Operation. Der erste leidet unter ernsthaften Effizienzproblemen, während der zweite zu ausführlich ist und eine mühsame Anstrengung ohne großen Gewinn darstellt.
RichN

4

Ternär, bedingt; Tomate, Tomate. Wofür es wirklich wertvoll ist, ist die variable Initialisierung. Wenn Sie (wie ich) gerne Variablen dort initialisieren, wo sie definiert sind, können Sie dies mit dem bedingten ternären Operator (denn es ist beides) in Fällen tun, in denen eine Konditionalität über ihren Wert besteht. Besonders bemerkenswert in den letzten Bereichen, aber auch anderswo nützlich.

z.B:

public class Foo {
    final double    value;

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

Ohne diesen Operator - mit welchem ​​Namen auch immer - müssten Sie das Feld nicht endgültig machen oder eine Funktion schreiben, um es einfach zu initialisieren. Eigentlich ist das nicht richtig - es kann immer noch mit if / else initialisiert werden, zumindest in Java. Aber ich finde das sauberer.



3

Dieses Konstrukt wird in Informatik und Programmiertechniken als ternärer Operator bezeichnet .
Und Wikipedia schlägt folgende Erklärung vor:

In der Informatik ist ein ternärer Operator (manchmal fälschlicherweise als tertiärer Operator bezeichnet) ein Operator, der drei Argumente akzeptiert. Die Argumente und das Ergebnis können unterschiedlicher Art sein. Viele Programmiersprachen, die eine C-ähnliche Syntax verwenden, verfügen über einen ternären Operator?:, Der einen bedingten Ausdruck definiert.

Diese Syntax ist nicht nur in Java, sondern auch in PHP und Objective-C verfügbar.

Im folgenden Link gibt es die folgende Erklärung, die ziemlich gut zu verstehen ist:

Ein ternärer Operator ist eine Operation, die an 3 Eingängen arbeitet. Es ist eine Verknüpfung für eine if-else-Anweisung und wird auch als bedingter Operator bezeichnet.

In Perl / PHP funktioniert es wie folgt:
boolean_condition ? true_value : false_value

In C / C ++ funktioniert es wie folgt:
logical expression ? action for true : action for false

Dies kann für einige logische Bedingungen lesbar sein, die nicht zu komplex sind. Andernfalls ist es besser, den If-Else-Block mit der beabsichtigten Kombination von bedingter Logik zu verwenden.

Mit diesem ternären Operator können wir die If-Else-Blöcke für eine Code-Anweisungszeile vereinfachen .
Beispielsweise:

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

Könnte gleich sein wie folgt:

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

Wenn wir uns also auf Ihre Aussage beziehen:

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

Es ist tatsächlich das 100% -Äquivalent des folgenden If-Else-Blocks :

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

Das ist es!
Hoffe das war hilfreich für jemanden!
Prost!


2

Richtig. Es nennt die ternäre Operator . Einige nennen es auch den bedingten Operator .


9
Um Alice im Wunderland zu zitieren, wird es als ternärer Operator bezeichnet, aber sein Name ist der bedingte Operator.
Paul Tomblin

Der Name wird jedoch als Fragezeichen-Doppelpunktoperator bezeichnet.
Michael Myers

1
Das Benennen von Namen klingt ein bisschen C ++ ish. Der Fragezeichen-Doppelpunktoperator ?: (Ein Token) wird als Elvis-Operator bezeichnet.
Tom Hawtin - Tackline

2

Sein ternärer Operator (? :)

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

Möglicherweise interessieren Sie sich für einen Vorschlag für einige neue Operatoren, die dem bedingten Operator ähnlich sind. Die null-sicheren Operatoren aktivieren Code wie folgt:

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

Es wäre besonders praktisch, wenn das automatische Entpacken stattfindet.

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

Es wurde zur weiteren Prüfung unter JDK 7s "Project Coin" ausgewählt.


Dieser Operator ist nicht einer meiner Favoriten von Project Coin. Eingeschränkte Nützlichkeit, nicht intuitiv zu lesen und einfach nur hässlich wie alle anderen. Vielleicht würde es aber an mir wachsen.
Michael Myers

Eigentlich bin ich auch kein großer Fan. Es ist ein Vorschlag von Neal Gafter, und er sieht die Dinge ganz anders als ein durchschnittlicher Java-Programmierer, der die Dinge anders sieht als ein durchschnittlicher Mensch. Die einzigen Stellen, an denen ich ein wenig Hilfe bei Nullen haben möchte, sind eine foreach-Schleife, in der getestet wird, ob die Iterable null ist, und das automatische Entpacken.
Erickson

IIRC <Neal hat es nicht vorgeschlagen. Er hat es nur als einfaches Beispiel dafür verwendet, wie man einen Vorschlag schreibt. Weitere Details zum Projektmünz-Mailinglisten-Archiv.
Tom Hawtin - Tackline

Ich habe gerade das Intro zum Vorschlag gelesen, und Sie haben Recht. Es ist Stephen Colebourne von Joda und "Es gibt kein Java 7" Ruhm.
Erickson

1

Tatsächlich kann es mehr als 3 Argumente dauern. Wenn wir beispielsweise prüfen möchten, ob eine Zahl positiv, negativ oder null ist, können wir dies tun:

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

Das ist besser als wenn, sonst wenn, sonst.


0

Es ist der bedingte Operator und mehr als nur eine präzise Schreibweise für if-Anweisungen.

Da es sich um einen Ausdruck handelt, der einen Wert zurückgibt, kann er als Teil anderer Ausdrücke verwendet werden.


0

Ja du hast Recht. ?: wird typischerweise als "ternärer bedingter Operator" bezeichnet, der oft einfach als "ternärer Operator" bezeichnet wird. Es ist eine Kurzversion des Standards, wenn / sonst bedingt.

Ternärer bedingter Operator


0

Ich mag diesen Operator wirklich, aber der Leser sollte berücksichtigt werden.

Sie müssen die Codekompaktheit immer mit der Zeit abwägen, die Sie für das Lesen aufgewendet haben, und darin gibt es einige ziemlich schwerwiegende Fehler.

Zuallererst gibt es den Fall des Original Asker. Er verbrachte nur eine Stunde damit, darüber zu posten und die Antworten zu lesen. Wie lange hätte der Autor gebraucht, um jeden zu schreiben ?: Als Wenn / Dann im Laufe seines ganzen Lebens. Keine Stunde, um sicher zu sein.

Zweitens haben Sie in C-ähnlichen Sprachen die Angewohnheit, einfach zu wissen, dass Bedingungen das erste sind, was in der Zeile steht. Ich bemerkte dies, als ich Ruby verwendete und stieß auf Zeilen wie:

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

Wenn ich lange Zeit Ruby-Benutzer gewesen wäre, hätte ich wahrscheinlich kein Problem mit dieser Zeile gehabt, aber wenn Sie von C kommen und "callMethodWhatever" als erstes in der Zeile sehen, erwarten Sie, dass sie ausgeführt wird. Das ?: Ist weniger kryptisch, aber immer noch ungewöhnlich genug, um einen Leser auszuschalten.

Der Vorteil ist jedoch ein wirklich cooles Gefühl in Ihrem Bauch, wenn Sie eine 3-zeilige if-Anweisung in den Raum von 1 der Zeilen schreiben können. Kann das nicht leugnen :) Aber ehrlich gesagt, nicht unbedingt besser lesbar für 90% der Leute da draußen, einfach wegen seiner Seltenheit.

Wenn es sich wirklich um eine Aufgabe handelt, die auf einem Booleschen Wert und Werten basiert, habe ich kein Problem damit, aber es kann leicht missbraucht werden.


0

Bedingte Ausdrücke haben einen völlig anderen Stil, ohne explizites Wenn in der Anweisung.

Die Syntax lautet: Boolescher Ausdruck? Ausdruck1: Ausdruck2;

Das Ergebnis dieses bedingten Ausdrucks ist

expression1 wenn boolean-expression wahr ist;

Andernfalls lautet das Ergebnis expression2.

Angenommen, Sie möchten die größere Anzahl der Variablen num1 und num2 max. Sie können einfach eine Anweisung mit dem bedingten Ausdruck schreiben: max = (num1> num2)? num1: num2;

Hinweis: Die Symbole? und: erscheinen zusammen in einem bedingten Ausdruck. Sie bilden einen bedingten Operator und werden auch als ternärer Operator bezeichnet, da drei Operanden verwendet werden. Es ist der einzige ternäre Operator in Java.

zitiert aus: Einführung in die Java-Programmierung 10. Ausgabe von Y. Daniel Liang Seite 126 - 127

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.