简体   繁体   中英

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.

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.

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 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

You are right, the explanation is confusing as different compatible types can be used for the right hand expressions.

You can find a table of the resulting type of the conditional expression according to the types of the second and third operand here .

There can be some type casting with numeric types, as explained in this question .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM