LINUX.ORG.RU

Java beginner static field

 


0

1
package com;
class Test {
    public static Test test = new Test();
    public static int level = 0;
    Test() {
        level = 1;
        System.out.println("Test() " + level);
    }
}
public class Main {
    public static void main(String[] arg) {
        System.out.println("level " + Test.level);
        System.out.println("level " + Test.test.level);
    }
}
Output:
Test() 1
level 0
level 0

Q: Это нормально в java? openjdk version «11.0.16» 2022-07-19 OpenJDK Runtime Environment (build 11.0.16+8-post-Ubuntu-0ubuntu120.04) OpenJDK 64-Bit Server VM (build 11.0.16+8-post-Ubuntu-0ubuntu120.04, mixed mode, sharing)



Последнее исправление: kdev (всего исправлений: 1)

Инициализация и вызов конструктора test выполняется раньше инициализации level.

Поменяйте их местами и получите ожидаемое поведение.

unDEFER ★★★★★
()

Если бы мне на интервью дали такой код я бы предположил иной вывод

System.out.println("level " + Test.test.level);

Здесь должно было произойти создание экземпляра класса Test с вызовом конструктора, где должно было присвоено 1 полю level, а значит это значение должно было быть отпечатано, типа так.

level 0
level 1

Но здесь серая зона, на статических полях не хватает модификатора volatile. Я думаю загрузка классов может происходить в другом треде от исполняемого кода. Нарушенный порядок вывод через println как бы подтверждает эту мысль.

А вообще есть правило - не обращаться к статичным полям через ссылки на экземпляры класса. Так не пишут: test.LEVEL, наверное в этом случае никаких гарантий на последовательность исполняемых операций нет (нужно читать спеку JVM), возможно Test.test.х автоматически заменяется на просто Test.х если поле x static.

Aber ★★★★★
()
Ответ на: комментарий от Aber

Похоже я много всего лишнего наговорил, overthinking и невнимательность.

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

public static Test test = new Test();
public static int level = 0;

Тык что тут все очень просто, вначале присваивается 1 в конструкторе, потом этому же статическому полю присваивается 0.

Aber ★★★★★
()
Ответ на: комментарий от Aber

Если бы мне на интервью дали такой код

Я бы сказал, что автора кода надо уволить. Не стоит полагаться на порядок инициализации в принципе. Даже если это работает, всё равно это «хитрый» код и так писать не надо.

no-such-file ★★★★★
()
Ответ на: комментарий от Aber

На интервью бывает дают поломанный код и просят объяснить его работу

Просто вставай и уходи. Это всё равно что при приёме в грузчики просить крутануть сальто для проверки физической формы. Нафиг тебе контора, где критическим навыком сотрудников является умение разбираться в говнокоде?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

отказ грузчика грузить мешки с мотивировкой «а нас учили тока ящики грузить, там есть за шо хвататься, а тут за шо» является дисквалифицирующим деянием и наказывается изгнанием грузчика методом пинка по жопе.

olelookoe ★★★
()
Ответ на: комментарий от olelookoe

Вообще-то грузчик будет прав. Без схемы строповки грузить нельзя. Т.к. если что-то сломается он будет виноват.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)

А ещё можно воткнуть статический инициализатор вместо конструктора (вместо Test(){ сделать static{ ) - будет другое поведение :-)

rukez ★★★★
()
Ответ на: комментарий от Aber

Код то нормальный (хотя и упрощенный), в с++ по другому работает. А что там java (JLS) понапридумывали, понаоптимызировали, её дело. Все static до main(), и что javac не ругается?

...
int Test::level = 0;
Test* Test::test = new Test();
kdev
() автор топика
Последнее исправление: kdev (всего исправлений: 2)
Ответ на: комментарий от iZEN

придерживаются того, что описано в JLS.

Там написано что надо писать говнокод? У тебя есть опция прямо сейчас спрыгнуть с крыши. Почему ты до сих пор не прыгаешь?

no-such-file ★★★★★
()