web-dev-qa-db-fra.com

Les deux expressions de droite d'un opérateur ternaire doivent-elles être de types compatibles?

Le livre My Practice Tests contient cette question sur l'opérateur ternaire:

// What is the output of the following application?
public class Transportation {
    public static String travel(int distance) {
        return(distance < 1000 ? "train" : 10);
    }
    public static void main(String[] args) {
        travel(500);
    }
}

Il ne compile pas. L'explication donnée est la suivante:

Les opérations ternaires exigent que les deux expressions de la main droite soient de types de données compatibles. Dans cet exemple, la première main droite l'expression de l'opération ternaire externe est de type String, alors que le la deuxième expression de droite est de type int. Depuis ces types de données sont incompatibles, le code ne compile pas et Option C est le bonne réponse.

Est-ce vraiment la raison? Il me semble que cet exemple ne compile pas parce que 10 n'est pas une chaîne et qu'une chaîne est ce que la méthode doit renvoyer . Je demande parce que System.out.println(distance < 1000 ? "train" : 10); un problème.

13
mgr326639

Votre méthode déclare que le type de retour est String. Toute instruction return doit générer une expression compatible avec le type de retour déclaré.

Dans ce cas, cependant, le type de retour peut être int, ce qui explique pourquoi le compilateur le rejette.

Ceci n'est pas spécifique à l'opérateur ternaire, il peut également être reproduit avec un bloc if/else équivalent:

if(distance < 1000)
   return "train"; //This part is valid
else
    return 10; //This line will be rejected by the compiler

Pour la même raison, la dernière ligne ne sera pas compilée. Ceci est simplement dû à la vérification de type de base.

System.out.println (distance <1000? "Train": 10); compile et fonctionne sans problème.

En effet, le compilateur détecte un type commun à la fois pour String et int, qui est Object, et décide de choisir cette signature:

Java.io.PrintStream#println(Object x) // available in the target class

Ceci, cependant, n'est pas applicable au type de retour de méthode.

Si vous avez changé votre type de retour en Object, votre code sera également compilé. Mais ce n'est bien sûr pas ce que vous essayez de faire.

Les opérations ternaires exigent que les deux expressions de droite soient de types de données compatibles

-> Cette partie est en fait valide. voici une façon de l'interpréter: chaque des deux expressions doit être individuellement compatible:

String value = distance > 1000 ?
                 "train" //this must be compatible with String
                 :
                 10 //this too must be compatible with String (it isn't)

En revanche:

Object value = distance > 1000 ?
                 "train" //this must be compatible with Object (it is)
                 :
                 10 //this too must be compatible with Object (it is)

En d'autres termes, l'appel à System.out.println(distance < 1000 ? "train" : 10) est similaire au dernier exemple ci-dessus, où le type attendu est compatible avec les deux expressions.

14
ernest_k

est-ce vraiment la raison? Il me semble que cet exemple ne compile pas car 10 n'est pas une chaîne et une chaîne correspond à la méthode doit revenir 

Votre raisonnement et la réponse de l'auteur ont raison.
Je pense que la bonne réponse à votre question est leur union.

1) l'opérateur ternaire est invalide 

parce que 

2) dans le contexte actuel, le type auquel vous l'avez affecté: une int ne peut pas être affecté à une String

Vous pouvez le vérifier avec les messages d'erreur émis par le compilateur. 

Ici, vous devez considérer que:

return(distance < 1000 ? "train" : 10);

comme deux choses à évaluer par le compilateur:

1) distance < 1000 ? "train" : 10 // produit un résultat

2) returns (the produced result); // retourne le résultat qui devrait être assignable à une chaîne en fonction du type de retour de la méthode

En fait, l'erreur de compilation: 

Transportation.Java:3: erreur: types incompatibles: mauvais type dans expression conditionnelle retour (distance <1000? "train": 10);
int ne peut pas être converti en chaîne

renvoie les deux erreurs: l'erreur dans l'expression conditionnelle et sa cause: l'erreur de l'incompatibilité entre int et String

Ainsi, l'erreur de compilation qui fait référence à uniquement l'incompatibilité entre int et String dans la variable return se produira uniquement si le ternaire est valide au moment de la compilation. 

Ecrivez une expression ternaire valide et vous verrez que le compilateur ne signalera que l'erreur concernant l'instruction return:

public static String travel(int distance) {
    return(distance < 1000 ? 15 : 10);
}

erreur: types incompatibles: int ne peut pas être converti en chaîne

5
davidxxx

Vous avez raison, l'explication est déroutante, car différents types compatibles peuvent être utilisés pour les expressions de droite. 

Vous pouvez trouver une table du type résultant de l'expression conditionnelle en fonction des types des deuxième et troisième opérandes ici .

Il peut y avoir des transtypages avec des types numériques, comme expliqué dans cette question .

0
Jacques Gaudin