Почему 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;
}

Этот метод включает условное выражение (), где:

  1. первое выражениеo == null
  2. второе выражение
  3. третье выражение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)).

Другие вопросы по тегам