Qu'est-ce que l'opérateur Java?: Appelé et que fait-il?


161

Je travaille avec Java depuis quelques années, mais jusqu'à récemment, je n'ai pas rencontré cette construction:

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

C'est probablement une question très simple, mais quelqu'un peut-il l'expliquer? Comment le lire? Je suis presque sûr de savoir comment cela fonctionne.

  • si isHereest vrai, getHereCount()est appelé,
  • si isHereest faux getAwayCount()est appelé.

Correct? Comment s'appelle cette construction?


2
Voir aussi stackoverflow.com/questions/795286/what-does-do-in-c pour la version C ++ de cette question (posée juste hier, en fait).
Michael Myers

2
Gardez à l'esprit que le monde C / C ++ / Java est assez équitablement divisé entre les personnes qui pensent que c'est moche et déroutant et l'éviteront comme la peste, et les personnes qui pensent que vous ne pouvez pas vraiment prétendre connaître C, C ++ ou Java si vous ne peut pas le reconnaître et l'utiliser sans faire une pause pour réfléchir.
Paul Tomblin

3
Il est généralement considéré comme une mauvaise forme en Java de l'utiliser au-delà des cas les plus clairs et les plus simples. Si vous vous trouvez en train de les nicher, vous vous en sortez. D'autre part, dans la culture C où le code rapide et intelligent est valorisé au-dessus de la clarté, il est considéré comme acceptable.
Yishai

17
answer_to_question = (identifier_opérateur)? (social_acceptance): (condescending_finger_wag)
Dan

Vous pouvez consulter cette ressource pour plus d'informations.
Shiva

Réponses:


189

Oui, c'est une forme abrégée de

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

C'est ce qu'on appelle l' opérateur conditionnel . Beaucoup de gens l'appellent (à tort) l'opérateur ternaire , car c'est le seul opérateur ternaire (trois arguments) en Java, C, C ++ et probablement dans de nombreux autres langages. Mais en théorie, il pourrait y avoir un autre opérateur ternaire, alors qu'il ne peut y avoir qu'un seul opérateur conditionnel .

Le nom officiel est donné dans la spécification du langage Java :

§15.25 Opérateur conditionnel? :

L'opérateur conditionnel ? :utilise la valeur booléenne d'une expression pour décider laquelle des deux autres expressions doit être évaluée.

Notez que les deux branches doivent conduire à des méthodes avec des valeurs de retour:

Il s'agit d'une erreur de compilation pour que la deuxième ou la troisième expression d'opérande soit une invocation d'une méthode void.

En fait, par la grammaire des déclarations d'expression ( §14.8 ), il n'est pas permis pour une expression conditionnelle d'apparaître dans un contexte où une invocation d'une méthode void pourrait apparaître.

Donc, si doSomething()et doSomethingElse()sont des méthodes void, vous ne pouvez pas compresser ceci:

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

dans ceci:

someBool ? doSomething() : doSomethingElse();

Mots simples:

booleanCondition ? executeThisPartIfBooleanConditionIsTrue : executeThisPartIfBooleanConditionIsFalse 

Je ne comprends pas ce que le bas fait de mal. Je te crois et tout le monde. Cela me ressemble à l'original. Est-ce parce qu'ils appellent simplement une autre fonction qui peut ou non retourner une valeur et permettre l'exécution du jeu de codes suivant?
johnny

8
Je suppose que doSomething () et doSomethingElse () sont des méthodes vides. Ce que dit ce dernier bit de la spécification, c'est que l'opérateur ternaire doit renvoyer une valeur, donc aucun des opérandes ne peut être des méthodes vides.
Michael Myers

Cela en dit un peu plus. Il dit que l'opérateur conditionnel n'est pas autorisé là où une méthode void POURRAIT apparaître. Ainsi, par exemple, les instructions suivantes: VALID: String x = (false)? "X": "Y"; NON VALIDE: (faux)? "X": "Y";
kenj0418

4
Il n'est pas erroné de l'appeler «l'opérateur ternaire», tout comme il n'est pas erroné (en 2016) de qualifier Obama de «président», même s'il est possible qu'il y ait d'autres présidents dans le futur.
Dawood ibn Kareem

2
@DawoodibnKareem Je pense que Michael a délibérément inclus thedans l'italique de the ternary operator, et c'est ce qu'il veut dire est erroné, non pas que ternary operatorc'est faux. L' opérateur ternaire implique que, comme Michael dit, il est le seul, ce qui pourrait conduire à supposer qu'il ne peut y avoir d' autres opérateurs ternaires, ce qui est ce que Michael dit est erroné, et je suis d' accord, ce serait être une hypothèse erronée.
Ghoti and Chips

32

D'autres y ont répondu dans une mesure raisonnable, mais souvent sous le nom d '«opérateur ternaire».

Étant le pédant que je suis, je voudrais préciser que le nom de l'opérateur est l'opérateur conditionnel ou "opérateur conditionnel?:". C'est un opérateur ternaire (en ce sens qu'il a trois opérandes) et il se trouve être le seul opérateur ternaire en Java pour le moment.

Cependant, la spécification est assez claire que son nom est l'opérateur conditionnel ou "opérateur conditionnel?:" Pour être absolument sans ambiguïté. Je pense qu'il est plus clair de l'appeler par ce nom, car cela indique le comportement de l'opérateur dans une certaine mesure (évaluation d'une condition) plutôt que simplement le nombre d'opérandes dont il dispose.


3
Cette réponse est techniquement correcte. Cependant, comme il n'y a qu'un seul opérateur ternaire, vous le voyez souvent appelé l'opérateur ternaire. Même si ce nom ne transmet pas la signification complète de l'opérateur, c'est un nom qui est resté bloqué. Si vous mentionnez le nom "opérateur ternaire", les programmeurs savent de quoi vous parlez. La spécification que vous mentionnez fait également référence à cet opérateur sous le nom de «conditionnel ternaire» qui semble plus informatif. java.sun.com/docs/books/jls/third_edition/html/…
Gary

17
Je pense juste qu'il vaut la peine d'appeler quelque chose par son nom défini. En particulier, si Java obtient un jour un autre opérateur ternaire, les personnes qui utilisent le terme «opérateur conditionnel» seront toujours correctes et sans ambiguïté - contrairement à celles qui disent simplement «opérateur ternaire». Oui, l'expression «opérateur ternaire» est restée bloquée - ma réponse fait partie d'un effort pour la «décoller», tout comme j'essaie de corriger l'affirmation selon laquelle «les objets sont passés par référence».
Jon Skeet

1
Puis-je vous diriger vers cette page d'Oracle qui parle de trois "opérateurs conditionnels" mais d'un seul "opérateur ternaire"? Si vous voulez préciser de quel opérateur vous parlez, il est probablement préférable d'utiliser le nom que la plupart des gens utilisent. (Oui, je sais que je me présente à la fête au moment où l'hôte lave la dernière vaisselle).
Dawood ibn Kareem

@DavidWallace: Utiliser "l'opérateur conditionnel?:" Est mieux, l'OMI - éditera pour clarifier cela. Mais je pense qu'il vaut la peine de persuader les gens d'utiliser le nom réel de l'opérateur plutôt que de se concentrer sur un aspect de celui-ci (combien d'opérandes il a) qui n'a rien à voir avec son comportement. (Il n'est pas rare non plus que les didacticiels soient moins précis que la spécification, qui appelle &&l'opérateur conditionnel-and, et ||l'opérateur conditionnel-or, mais n'utilise que "l'opérateur conditionnel" pour ?:.
Jon Skeet

Je ne sais pas. Si quelqu'un me dit «opérateur conditionnel», je ne sais pas ce qu'il veut dire. D'où je viens (à l'autre bout du monde de vous), les gens ne l'appellent tout simplement pas ainsi. S'ils disent "opérateur ternaire" ou "opérateur crochet", alors je comprends. J'admire votre ambition, vouloir changer la façon dont les gens parlent. Si quelqu'un peut le faire, c'est vous. Mais je n'ai pas beaucoup d'espoir et je ne vois pas grand chose.
Dawood ibn Kareem

17

Selon la spécification Sun Java , il s'appelle l'opérateur conditionnel. Voir la section 15.25. Vous avez raison sur ce qu'il fait.

L'opérateur conditionnel? : utilise la valeur booléenne d'une expression pour décider laquelle des deux autres expressions doit être évaluée.

L'opérateur conditionnel est syntaxiquement associatif à droite (il regroupe de droite à gauche), de sorte que a? B: c? D: e? F: g signifie la même chose que a? B: (c? D: (e? F :g)).

ConditionalExpression:
        ConditionalOrExpression
        ConditionalOrExpression ? Expression : ConditionalExpression

L'opérateur conditionnel a trois expressions d'opérande; ? apparaît entre les première et deuxième expressions, et: apparaît entre les deuxième et troisième expressions.

La première expression doit être de type booléen ou booléen, sinon une erreur de compilation se produit.


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

veux dire :

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

5

Pas tout à fait correct, pour être précis:

  1. si isHere est vrai, le résultat de getHereCount () est retourné
  2. otheriwse le résultat de getAwayCount () est retourné

Ce «rendu» est très important. Cela signifie que les méthodes doivent renvoyer une valeur et que cette valeur doit être affectée quelque part.

De plus, ce n'est pas exactement équivalent syntaxiquement à la version if-else. Par exemple:

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

Si codé avec if-else donnera toujours plus de bytecode.


Je crois que javac est libre de générer le même bytecode. Bien que vous ayez raison, il existe des cas de coin obscurs où ils ne sont pas équivalents.
Tom Hawtin - tackline

Oui bien sûr. Pour moi, le vrai mérite de l'opérateur conditionnel est l'exemple que j'ai donné. Les alternatives sont soit: // gasp !! String temp = str1; if (vérifier) ​​temp + = str2; sinon temp + = str3; temp + = str4; température de retour; ou coder manuellement l'opération d'ajout de StringBuilder. Le premier souffre d'un sérieux problème d'efficacité tandis que le second est trop verbeux et représente un effort minutieux sans grand gain.
RichN

4

Ternaire, conditionnel; tomate, tomate. Ce qui est vraiment utile, c'est l'initialisation des variables. Si (comme moi) vous aimez initialiser les variables là où elles sont définies, l'opérateur ternaire conditionnel (car c'est les deux) vous permet de le faire dans les cas où il y a une conditionnalité sur sa valeur. Particulièrement remarquable dans les domaines finaux, mais également utile ailleurs.

par exemple:

public class Foo {
    final double    value;

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

Sans cet opérateur - quel que soit son nom - il faudrait rendre le champ non final ou écrire une fonction simplement pour l'initialiser. En fait, ce n'est pas correct - il peut toujours être initialisé en utilisant if / else, du moins en Java. Mais je trouve cela plus propre.



3

Cette construction est appelée opérateur ternaire en informatique et techniques de programmation.
Et Wikipedia suggère l'explication suivante:

En informatique, un opérateur ternaire (parfois appelé à tort opérateur tertiaire) est un opérateur qui prend trois arguments. Les arguments et le résultat peuvent être de différents types. De nombreux langages de programmation qui utilisent une syntaxe de type C comportent un opérateur ternaire,?:, Qui définit une expression conditionnelle.

Non seulement en Java, cette syntaxe est disponible dans PHP, Objective-C aussi.

Dans le lien suivant , il donne l'explication suivante, ce qui est assez bon pour le comprendre:

Un opérateur ternaire est une opération fonctionnant sur 3 entrées. C'est un raccourci pour une instruction if-else, et est également connu comme un opérateur conditionnel.

En Perl / PHP, cela fonctionne comme:
boolean_condition ? true_value : false_value

En C / C ++, cela fonctionne comme:
logical expression ? action for true : action for false

Cela peut être lisible pour certaines conditions logiques qui ne sont pas trop complexes, sinon il est préférable d'utiliser le bloc If-Else avec la combinaison prévue de logique conditionnelle.

Nous pouvons simplifier les blocs If-Else avec cet opérateur ternaire pour une ligne de déclaration de code.
Par exemple:

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

Peut être égal à ce qui suit:

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

Donc, si nous nous référons à votre déclaration:

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

C'est en fait l'équivalent à 100% du bloc If-Else suivant :

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

C'est tout!
J'espère que cela a été utile à quelqu'un!
À votre santé!


2

Correct. C'est ce qu'on appelle l' opérateur ternaire . Certains l'appellent également l' opérateur conditionnel .


9
Pour citer Alice au pays des merveilles, on l'appelle l'opérateur ternaire, mais son nom est l'opérateur conditionnel.
Paul Tomblin

Mais le nom de celui-ci est appelé l'opérateur deux points de point d'interrogation.
Michael Myers

1
Nommer le nom sonne un peu C ++. L'opérateur deux-points de point d'interrogation?: (Un jeton) est connu sous le nom d'opérateur Elvis.
Tom Hawtin - tackline

2

Son opérateur ternaire (? :)

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

Vous pourriez être intéressé par une proposition pour certains nouveaux opérateurs similaires à l'opérateur conditionnel. Les opérateurs null-safe activeront un code comme celui-ci:

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

Ce serait particulièrement pratique lorsque le déballage automatique a lieu.

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

Il a été sélectionné pour un examen plus approfondi dans le cadre du «Project Coin» de JDK 7.


Cet opérateur n'est pas l'un de mes favoris de Project Coin. Utilité limitée, pas intuitif à lire, et tout simplement moche comme tout le monde sort. Peut-être que ça pousserait sur moi, cependant.
Michael Myers

Je ne suis pas non plus un grand fan, en fait. C'est une proposition de Neal Gafter, et il a tendance à voir les choses très différemment de votre programmeur Java moyen, qui a tendance à voir les choses différemment de votre être humain moyen. Les seuls endroits où je pourrais aimer un peu d'aide avec les nulls sont dans une boucle foreach, en testant si l'itérable est nul et en unboxing automatique.
erickson

IIRC <Neal ne l'a pas proposé. Il l'a simplement utilisé comme un exemple simple de rédaction d'une proposition. Plus de détails sur l'archive de la liste de diffusion des pièces de monnaie du projet.
Tom Hawtin - tackline

Je viens de lire l'introduction de la proposition, et vous avez raison. C'est Stephen Colebourne de Joda et "il n'y a pas de renommée Java 7".
erickson

1

En fait, cela peut prendre plus de 3 arguments. Par exemple, si nous voulons vérifier si un nombre est positif, négatif ou nul, nous pouvons le faire:

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

ce qui est mieux que d'utiliser if, else if, else.


0

C'est l'opérateur conditionnel, et c'est plus qu'une simple manière concise d'écrire des instructions if.

Puisqu'il s'agit d'une expression qui renvoie une valeur, elle peut être utilisée dans le cadre d'autres expressions.


0

Oui vous avez raison. ?: est généralement appelé «opérateur conditionnel ternaire», souvent appelé simplement «opérateur ternaire». Il s'agit d'une version abrégée du conditionnel if / else standard.

Opérateur conditionnel ternaire


0

Il se trouve que j'aime vraiment cet opérateur, mais le lecteur doit être pris en considération.

Vous devez toujours équilibrer la compacité du code avec le temps passé à le lire, et en ce sens qu'il présente de graves défauts.

Tout d'abord, il y a le cas de l'Original Asker. Il vient de passer une heure à poster à ce sujet et à lire les réponses. Combien de temps aurait-il fallu à l'auteur pour écrire tout?: Comme un si / alors tout au long de sa vie. Pas une heure pour être sûr.

Deuxièmement, dans les langages de type C, vous prenez l'habitude de simplement savoir que les conditions sont la première chose de la ligne. J'ai remarqué cela lorsque j'utilisais Ruby et suis tombé sur des lignes comme:

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

Si j'étais un utilisateur de Ruby depuis longtemps, je n'aurais probablement pas eu de problème avec cette ligne, mais venant de C, quand vous voyez "callMethodWwhat" comme la première chose dans la ligne, vous vous attendez à ce qu'elle soit exécutée. Le?: Est moins énigmatique, mais toujours assez inhabituel pour déranger un lecteur.

L'avantage, cependant, est une sensation vraiment cool dans votre ventre lorsque vous pouvez écrire une déclaration if de 3 lignes dans l'espace de 1 des lignes. Je ne peux pas le nier :) Mais honnêtement, pas nécessairement plus lisible par 90% des gens simplement à cause de sa «rareté».

Quand il s'agit vraiment d'une affectation basée sur un booléen et des valeurs, je n'ai pas de problème avec cela, mais il peut facilement être abusé.


0

Les expressions conditionnelles sont dans un style complètement différent, sans if explicite dans l'instruction.

La syntaxe est: expression-booléenne? expression1: expression2;

Le résultat de cette expression conditionnelle est

expression1 si l'expression booléenne est vraie;

sinon, le résultat est expression2.

Supposons que vous souhaitiez affecter le plus grand nombre de variables num1 et num2 à max. Vous pouvez simplement écrire une instruction en utilisant l'expression conditionnelle: max = (num1> num2)? num1: num2;

Remarque: les symboles? et: apparaissent ensemble dans une expression conditionnelle. Ils forment un opérateur conditionnel et également appelé opérateur ternaire car il utilise trois opérandes. C'est le seul opérateur ternaire en Java.

cité de: Introduction à la programmation Java 10e édition par Y. Daniel Liang pages 126-127

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.