Должны ли как правые выражения тернарного оператора быть совместимыми типами?

В моей книге "Тесты практики" содержится этот вопрос о тройном операторе:

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

Он не компилируется. Ниже приводится объяснение:

Тернарные операции требуют, чтобы оба правых выражения соответствовали типам данных. В этом примере первое правое выражение внешней тройной операции имеет тип String, а второе правое выражение имеет тип int. Поскольку эти типы данных несовместимы, код не компилируется, а вариант C - правильный ответ.

Это действительно причина? Мне кажется, что этот пример не компилируется, потому что 10 не является String, а String - тем, что должен вернуть метод. Я спрашиваю, потому что System.out.println(distance < 1000? "train": 10); компилируется и работает без проблем.

Ответ 1

Ваш метод объявляет, что тип возврата - String. Любой оператор return должен выдать выражение, совместимое с объявленным типом возвращаемого значения.

В этом случае, однако, тип возврата может быть int, что объясняет, почему компилятор его отклоняет.

Это не относится к тернарному оператору, его можно воспроизвести с помощью эквивалентного блока if/else:

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

По той же причине последняя строка не скомпилируется. Это просто из-за базовой проверки типов.

System.out.println (расстояние <1000? "Поезд": 10); компилируется и работает без проблем.

Это связано с тем, что компилятор обнаруживает общий тип для String и int, который является Object, и решает выбрать эту подпись:

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

Это, однако, не применимо к типу возвращаемого метода.

Если вы изменили свой тип возврата на Object, ваш код тоже скомпилировался. Но это, конечно, не то, что вы пытаетесь сделать.

Тернарные операции требуют, чтобы оба правых выражения соответствовали типам данных

→ Эта часть действительно действительна. вот способ интерпретировать его: каждое из двух выражений должно быть индивидуально совместимым:

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

По сравнению:

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

Другими словами, вызов System.out.println(distance < 1000? "train": 10) аналогичен предыдущему примеру выше, где ожидаемый тип совместим с обоими выражениями.

Ответ 2

это действительно причина? Мне кажется, что этот пример не компилируется, потому что 10 не является String, а String - тем, что метод должен возвращать

Правильны и ваши рассуждения, и ответ автора.
Я думаю, что правильный ответ на ваш вопрос - это их объединение.

1) недействителен оператор Ternary

так как

2) в текущем контексте - тип, которому вы его назначили: int не может быть назначен для String.

Вы можете проверить его с помощью сообщений об ошибках, отправленных компилятором.

Здесь вы должны учитывать, что:

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

как две вещи для оценки компилятором:

1) distance < 1000? "train": 10 distance < 1000? "train": 10//дает результат

2) returns (the produced result); // возвращаем результат, который должен быть назначен String в соответствии с типом возвращаемого метода

Собственно, ошибка компиляции:

Transport.java:3: ошибка: несовместимые типы: плохой тип в условном выражении return (расстояние <1000? "Поезд": 10);
int не может быть преобразован в String

ссылается на обе ошибки: ошибка в условном выражении и его причина: ошибка несовместимости между int и String.

Таким образом, ошибка компиляции, которая ссылается только на несовместимость между int и String в return будет возникать только в том случае, если тройка действительна во время компиляции.

Напишите действительное тернарное выражение, и вы увидите, что компилятор будет сигнализировать только об ошибке в отношении оператора return:

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

error: несовместимые типы: int не может быть преобразован в String

Ответ 3

Вы правы, объяснение сбивает с толку, поскольку для правильных выражений можно использовать различные совместимые типы.

Вы можете найти таблицу результирующего типа условного выражения в соответствии с типами второго и третьего операнда здесь.

Может быть какой-то тип литья с числовыми типами, как объясняется в этом вопросе.