Почему javac не уловил эту троичную ошибку?
Ясно, что возвращение нулевого значения для логического типа является ошибкой. Почему Javac не ловит это?
public class Test {
public static void main(String[] args) {
Object a = null;
System.out.println(getThing(a));
}
private static boolean getThing(Object o) {
return o == null ? null : Boolean.TRUE;
}
}
1 ответ
Вопрос
Очевидно, что возврат null для логического типа является ошибкой. Почему javac не улавливает это?
Учитывая этот вопрос, вот соответствующая часть кода:
private static boolean getThing(Object o) {
return o == null ? null : Boolean.TRUE;
}
Этот метод включает условное выражение (), где:
- первое выражение
o == null
- второе выражение
- третье выражение
Boolean.TRUE
Почему он компилируется
Причинаjavac
позволяет это:
Условное выражение классифицируется как эталонное условное выражение (JLS 15.25.3) из-за второго и третьего выражений «null» и «Boolean.TRUE», взятых из JLS 15.25JLS 15.25:
Если и второе, и третье выражения операнда являются логическими выражениями, условное выражение является логическим условным выражением.
Если и второе, и третье выражения операнда являются числовыми выражениями, условное выражение является числовым условным выражением.
В противном случае условное выражение является ссылочным условным выражением.
Все условное выражение классифицируется как тип
java.lang.Boolean
Условное выражение имеет ссылочный тип, а тип возвращаемого значения метода — примитивный «логический» — может быть распакован из
Тип компилятора, «разрешающий» путь кода, где «нулевой» может быть распакован до «логического», не так уж сильно отличается от различных других очевидных ошибок программирования.
Например, вот код, который создает новый объект, присваивает ему значение , а затем пытается вызвать метод для этого объекта. Этот код компилируется нормально, но, что неудивительно, выдает исключение во время выполнения:
Object o = null;
System.out.println(o.hashCode());
Exception in thread "main" java.lang.NullPointerException:
Cannot invoke "Object.hashCode()" because "o" is null
Компилируется, но не запускается
Хотя ваш код компилируется, во время выполнения возникает следующее исключение, когда оно распаковывается в логическое значение:
Exception in thread "main" java.lang.NullPointerException:
Cannot invoke "java.lang.Boolean.booleanValue()"
В то время как возвращаемое значение оператораnull
– допустимое значение для – распаковка в логический примитив (чтобы соответствовать типу возвращаемого значения метода) вызывает исключение. Распаковка пытается позвонитьnull.booleanValue()
который не будет работать.
Вы не спрашивали, но простым решением было бы изменить возвращаемый тип метода с примитивногоboolean
кBoolean
. После этого ваша программа компилируется и запускается, печатая "null" (отSystem.out.println(getThing(a))
.