Явные выражения Java и устранение кода

Как обсуждалось здесь , javac и другие компиляторы Java могут предоставлять возможности устранения кода для if -statements, где условие "Constant Expression" .

Как это влияет, если мой код использует константное выражение, которое зависит от других константных выражений, определенных в разных пакетах?

Например, допустим, что у меня есть следующие классы в соответствующих указанных пакетах:

package foo;

public class Foo {
    public static final boolean CONDITION = false;
}

и

package bar;

import foo.Foo;

public class Bar {
    public void test() {
        if (Foo.CONDITION) {
            System.out.println("This line of code could be eliminated.");
        } else {
            System.out.println("This line of code will be executed.");
        }
    }
}

Очевидно, что если foo -пакет загружается во время выполнения из внешнего jar файла, компилятор не может технически просто предположить, что Foo.CONDITION будет ложным и не должен исключать true -branch состояния if.

Принимая во внимание, что если foo и Bar были фактически в одном пакете, true -branch определенно должен быть удален (если компилятор вообще поддерживает исключение кода).

Не совсем уверен, как лучше всего формулировать этот вопрос, но: Как "закрыть" foo должно быть Bar для постоянного выражения в foo также считаться постоянным в Bar? Должны ли они быть в одном файле? тот же пакет? тот же jar файл? или это вообще не имеет значения (т.е. будет ли компилятор всегда рассматривать Foo.CONDITION как константу и использовать значение, найденное в пути сборки во время компиляции)?

Ответ 1

Поскольку часть публичной "подписи" ссылочного класса считается постоянной. По сути, идея состоит в том, что final означает final, и если вы его измените, это ваша ошибка.

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

Обновление: на самом деле JLS дает еще более сильную гарантию:

Если поле является постоянной переменной (§4.12.4), то удаление ключевого слова окончательный или изменение его значения не нарушит совместимость с ранее существовавшие двоичные файлы, заставляя их не запускаться, но они не будут см. любое новое значение для использования поля, если они не являются перекомпилировать. Это истинно , даже если само использование не является выражение константы времени компиляции (§15.28).

Этот результат является побочным эффектом решения о поддержке условного компиляции, как обсуждалось в конце §14.21.

Ответ 2

Неважно, насколько близка ваша константа. Если это константа времени компиляции, определенная в specfication, она будет включена. Статические окончательные (константы) встроены в спецификацию Java (хотя я тоже не нашел спецификацию). Эта статья в java обсуждает тему в деталях. Соответствующий материал:

В соответствии с Спецификацией языка Java любое статическое конечное поле, инициализированное выражением, которое может быть оценено во время компиляции, должно быть скомпилировано в байтовый код, который "строит" значение поля. То есть динамическая ссылка не будет присутствовать внутри класса Main, чтобы сообщить значение A для интерфейса A во время выполнения. Вместо этого литерал 1 будет непосредственно компилироваться в Main.main().