Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Must both right-hand expressions of a ternary operator be of compatible types?

My Practice Tests book contains this question on the ternary operator:

// 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);
    }
}

It does not compile. The explanation given is the following:

Ternary operations require both right-hand expressions to be of compatible data types. In this example, the first right-hand expression of the outer ternary operation is of type String, while the second right-hand expression is of type int. Since these data types are incompatible, the code does not compile, and Option C is the correct answer.

Is that really the reason? It looks to me like this example doesn't compile because 10 is not a String and a String is what the method must return. I'm asking because System.out.println(distance < 1000 ? "train" : 10); compiles and runs without a problem.

like image 883
mgr326639 Avatar asked Jun 03 '18 18:06

mgr326639


People also ask

What are the three conditions in a ternary operator?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.

Which of the following is the correct syntax for a ternary operator?

?: = Question Mark Colon is also called C Ternary Operator.

Why we should not use ternary operator?

Except in very simple cases, you should discourage the use of nested ternary operators. It makes the code harder to read because, indirectly, your eyes scan the code vertically. When you use a nested ternary operator, you have to look more carefully than when you have a conventional operator.

What is a ternary operator how it is used to compare 3 operators?

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. If it helps you can think of the operator as shortened way of writing an if-else statement.


2 Answers

Your method declares that the return type is String. Any return statement must produce an expression that is compatible with the declared return type.

In this case, however, the return type can be int, which explains why the compiler rejects it.

This is not specific to the ternary operator, it can be reproduced with an equivalent if/else block as well:

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

For the same reason, the last line will fail to compile. This is simply because of basic type checking.

System.out.println(distance < 1000 ? "train" : 10); compiles and runs without a problem.

This is because the compiler detects a common type for both String and int, which is Object, and resolves to choose this signature:

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

This, however, isn't applicable to the method return type.

If you changed your return type to Object, your code would compile too. But that's of course not what you're trying to do.

Ternary operations require both right-hand expressions to be of compatible data types

-> This part is in fact valid. here's a way to interpret it: each of the two expressions must be individually compatible:

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

In contrast:

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

In other words, the call to System.out.println(distance < 1000 ? "train" : 10) is similar to the last example above, where the expected type is compatible with both expressions.

like image 195
ernest_k Avatar answered Oct 09 '22 16:10

ernest_k


is that really the reason? It looks to me like this example doesn't compile because 10 is not a String and a String is what the method must return

Both your reasoning and the answer of the author are right.
I think that the right answer to your question is the union of them.

1) the Ternary operator is invalid

because

2) in the current context, the type that you assigned it to : an int cannot be assigned to a String.

You can check it with the error messages emitted by the compiler.

Here, you have to consider that :

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

as two things to evaluate by the compiler :

1) distance < 1000 ? "train" : 10 // produces a result

2) returns (the produced result); // return the result that should be assignable to a String according to the method return type

Actually, the compilation error :

Transportation.java:3: error: incompatible types: bad type in conditional expression return(distance < 1000 ? "train" : 10);
int cannot be converted to String

refers the both errors : the error in the conditional expression and its cause : the error of the incompatibility between int and String.

So the compilation error that refers only the incompatibility between int and String in the return will occur only if the ternary is valid at compile time.

Write a valid ternary expression and you could see that the compiler will signal only the error about the return statement :

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

error: incompatible types: int cannot be converted to String

like image 21
davidxxx Avatar answered Oct 09 '22 17:10

davidxxx