@iskateli

Что за фигурные скобки в Java?

Наткнулся на такую конструкцию в классе, не знаю даже как в гугле искать это.

static {
         System.out.println("Инициализация Initable2");
       }


Полный пример класса:

class Initable2 {
       static int staticNonFinal = 147;
       static {
         System.out.println("Инициализация Initable2");
       }
    }


Для чего используется, когда нужна такая конструкция?
  • Вопрос задан
  • 1154 просмотра
Решения вопроса 1
Vamp
@Vamp
Эта конструкция называется блоком статической инициализации. Есть ещё точно такой же блок динамической инициализации, только без ключевого слова static.

Блоки инициализации нужны для задания начальных значений полям класса.
class Initable2 {
    static int staticNonFinal;

    public static void main(String[] args) {
        System.out.println(staticNonFinal);
    }
}

Данный пример выведет ноль, хотя переменной staticNonFinal не присваивалось никакое значение. Java гарантирует, что любые поля класса будут проинициализированы "нулевым" значением. То есть компилятор неявно вставляет в класс блок статической инициализации, в котором переменной staticNonFinal присваивается ноль.

class Initable2 {
    static int staticNonFinal;

    // Вот этот блок будет добавлен к
    // вашему классу во время компиляции.
    static {
        staticNonFinal = 0;
    }

    public static void main(String[] args) {
        System.out.println(staticNonFinal);
    }
}


Разумеется, вы можете инициализировать переменные своими значениями:
class Initable2 {
    static int staticNonFinal = 42;

    static String a = "hello";

    static Cache<String, Integer> b = CacheBuilder.newBuilder()
        .maximumSize(100)
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .build();
}

И тогда компилятор в блоке инициализации будет подставлять ваши значения вместо нулей:
class Initable2 {
    static int staticNonFinal;

    static String a;

    static Cache<String, Integer> b;

    static {
        staticNonFinal = 42;
        a = "hello";
        b = CacheBuilder.newBuilder()
            .maximumSize(100)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();
    }
}

А если вашей переменной требуется какая-то сложная инициализация, которую одной строкой не представить (как в примере с Cache), то тогда вам придется написать блок инициализации явным образом вручную:
class Initable2 {
    static int staticNonFinal = 42;

    static Map<Integer, String> statusCodes = new HashMap<>();

    static {
        statusCodes.put(200, "OK");
        statusCodes.put(404, "Not Found");
        statusCodes.put(418, "I'm a teapot");
    }
}

И тогда компилятор сгенерирует вам такой код:
class Initable2 {
    static int staticNonFinal;

    static Map<Integer, String> statusCodes;

    static {
        staticNonFinal = 42;
        statusCodes = new HashMap<>()
        statusCodes.put(200, "OK");
        statusCodes.put(404, "Not Found");
        statusCodes.put(418, "I'm a teapot");
    }
}


Точно таким же способом инициализируются и нестатические поля при помощи блока динамической инициализации (перед таким блоком отсутствует ключевое слово static и выглядит как просто фигурные скобки в теле класса). Каждый раз при создании объекта класса сначала выполняется блок динамической инициализации, а затем конструктор. Именно в таком порядке. Блок статической инициализации выполняется один раз при загрузке класса в память.

Блоки динамической инициализации редко используются программистами, так как проще всего сделать "инициализацию" в конструкторе (в кавычках, потому что формальная инициализация уже была выполнена перед запуском конструктора и конструктор просто переписывает уже инициализированное значение своим, поэтому более точным термином здесь будет переприсваивание). Но блоки статической инициализации используются довольно часто, так как статических конструкторов не существует.

Вот эти все блоки инициализации были придуманы создателями языка java чтобы исключить целый класс лютых ошибок, связанных с доступом к неинициализированным переменным, характерный для языков си и си++.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
@Dmtm
Android
ну так там же написано - блок статической инициализации, можно в лог вывести что класс инициализировался, можно другие статические поля заполнить, вобщем разных проблем можно себе насоздавать
Ответ написан
xez
@xez Куратор тега Java
TL Junior Roo
public class InitDemo {

    static String staticString;
    String s;

    static {
        System.out.println("внутри static");
        staticString = "Инициализация статического поля";
        // s = "Тут нельзя обращаться к не static полям";
    }


    public InitDemo(String s) {
        System.out.println("внутри  конструктора");
        this.s = s; //  А в конструкторе уже можно
    }

    {
        System.out.println("внутри {}");
        s = staticString; // Это будет выполнено ДО конструктора
    }

    public static void main(String[] args) {
        var initDemo = new InitDemo("Строка из конструктора");

        System.out.println(initDemo.s);
    }
}

внутри static
внутри {}
внутри  конструктора
Строка из конструктора
Ответ написан
Комментировать
azerphoenix
@azerphoenix Куратор тега Java
Java Software Engineer
Добрый вечер.
Прочитайте про блоки нестатической и статической инициализации.
https://vertex-academy.com/tutorials/ru/bloki-inic...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы