Что в Java является константой, а что - нет?

119
26 апреля 2019, 06:10

До недавнего времени я был почти на 100% убеждён в том, что прекрасно понимаю сущность констант в языке программирования Java. Так было, пока я не наткнулся на один из примеров, который был представлен в JLS (Java Language Specification). Он немного поверг меня в ступор, и я не могу разобраться с этим вопросом вплоть до текущего момента.

Наверное, я не сильно ошибусь, если скажу, что типичных констант в языке программирования Java нет вообще (во всяком случае, если смотреть с колокольни какого-нибудь С++). Даже ключевое слово const, которое зарезервировано с незапамятных времён, но до сих пор не используется, как бы ненавязчиво намекает нам об этом (не уверен, но вроде бы это было сделано для того, чтобы сохранить обратную совместимость с С++ в том случае, если константы всё-таки будут введены в язык).

В качестве некоторого общепринятого суррогата используется связка модификаторов static final в процессе декларирования переменной. Если я правильно понимаю, то именно такие переменные и считаются константами с точки зрения программистского сообщества ЯП Java. В то же время, если заглянуть на просторах JLS в параграф, который посвящён инициализации классов и интерфейсов, мы можем наткнуться на один интересный момент. Небольшая выдержка оттуда:

Example 12.4.1-3. Interface Initialization Does Not Initialize Superinterfaces

interface I {
    int i = 1, ii = Test.out("ii", 2);
}
interface J extends I {
    int j = Test.out("j", 3), jj = Test.out("jj", 4);
}
interface K extends J {
    int k = Test.out("k", 5);
}
class Test {
    public static void main(String[] args) {
        System.out.println(J.i);
        System.out.println(K.j);
    }
    static int out(String s, int i) {
        System.out.println(s + "=" + i);
        return i;
    }
}

This program produces the output:

1
j=3
jj=4
3

The reference to J.i is to a field that is a constant variable (§4.12.4); therefore, it does not cause I to be initialized (§13.4.9).

The reference to K.j is a reference to a field actually declared in interface J that is not a constant variable; this causes initialization of the fields of interface J, but not those of its superinterface I, nor those of interface K.

Despite the fact that the name K is used to refer to field j of interface J, interface K is not initialized.

И вот этот момент мне совершенно непонятен! В интерфейсах все поля неявным образом помечаются как public static final (другими они и не могут быть), что мы и видим в приведённом примере. Все поля имеют совершенно одинаковый набор модификаторов, но при этом, поле J.i называют константной переменной, а K.j константой уже не является, если верить примеру, который приведён в JLS.

Что же такое константа с точки зрения JLS? Неужели это не абсолютно все статические финализированные поля? Правильно ли я понял, что при присваивании значения через его возврат функцией, мы уже не можем считать поле константой?

Answer 1

С точки зрения JLS:

A constant variable is a final variable of primitive type or type String that is initialized with a constant expression

То есть константа - это final переменная (причем речь не только о static и не только о полях) примитивного типа или типа String, которая проинициализирована константным выражением

Вызов метода константным выражением не является, поэтому K.j - это не константа

READ ALSO
Тестирование исключений

Тестирование исключений

У меня имеется метод:

164
Есть такой сервис, куда можно выложить код, и где любой желающий сможет его сразу запустить?

Есть такой сервис, куда можно выложить код, и где любой желающий сможет его сразу запустить?

Хочу протестить свой кодЛично я ошибок не нахожу(почти), другие люди находят

157
Как добавить иконки пунктам меню в SystemTray?

Как добавить иконки пунктам меню в SystemTray?

Подскажите пожалуйста, как добавить иконки к пунктам меню, которые расположены в системном трее (в данном случае к пункту "Профиль")В официальном...

136
Вложенный тернарный оператор

Вложенный тернарный оператор

Прохожу тест-задачу:

403