Java: Когда полезен статический блок инициализации? - PullRequest
61 голосов
/ 21 февраля 2012

В чем разница между инициализацией в блоке static:

public class staticTest {

    static String s;
    static int n;
    static double d;

    static {
        s = "I'm static";
        n = 500;
        d = 4000.0001;
    }
    ...

И индивидуальная статическая инициализация:

public class staticTest {

    static String s = "I'm static";
    static int n    = 500;
    static double d = 4000.0001;

    ....

Ответы [ 12 ]

77 голосов
/ 21 февраля 2012

Статические блоки инициализации позволяют выполнять более сложную инициализацию, например, используя условные выражения:

static double a;
static {
    if (SomeCondition) {
      a = 0;
    } else {
      a = 1;
    }
}

Или когда требуется больше, чем просто конструирование: при использовании компоновщика для создания вашего экземпляра, обработки исключений или работы, отличной отсоздание статических полей необходимо.

Блок статической инициализации также запускается после встроенных статических инициализаторов, поэтому действует следующее:

static double a;
static double b = 1;

static {
    a = b * 4; // Evaluates to 4
}
16 голосов
/ 21 февраля 2012

Типичное использование:

private final static Set<String> SET = new HashSet<String>();

static {
    SET.add("value1");
    SET.add("value2");
    SET.add("value3");
}

Как бы вы сделали это без статического инициализатора?

9 голосов
/ 21 февраля 2012

Обработка исключений во время инициализации является еще одной причиной.Например:

static URL url;
static {
    try {
        url = new URL("https://blahblah.com");
    }
    catch (MalformedURLException mue) {
        //log exception or handle otherwise
    }
}

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

5 голосов
/ 21 февраля 2012

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

4 голосов
/ 22 февраля 2012
Блок

static может использоваться для инициализации синглтона экземпляра, чтобы предотвратить использование синхронизированного getInstance() метода.

4 голосов
/ 21 февраля 2012

В вашем примере нет разницы; но часто начальное значение является более сложным, чем удобно выражается в одном выражении (например, это List<String>, содержимое которого лучше всего выражается for -циклом; или это Method, который может не существовать, поэтому исключение -обработчики), и / или статические поля должны быть установлены в определенном порядке.

3 голосов
/ 13 июля 2018

Вы можете использовать блок try / catch внутри static{}, как показано ниже:

MyCode{

    static Scanner input = new Scanner(System.in);
    static boolean flag = true;
    static int B = input.nextInt();
    static int H = input.nextInt();

    static{
        try{
            if(B <= 0 || H <= 0){
                flag = false;
                throw new Exception("Breadth and height must be positive");
            }
        }catch(Exception e){
            System.out.println(e);
        }

    }
}

PS: по ссылке с this !

3 голосов
/ 21 февраля 2012

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

Конечно, я почти всегда делаю свою статику final и указываю на неизменяемый объект.

2 голосов
/ 24 августа 2016

Статическое ключевое слово (будь то переменная или блок) принадлежит классу.Поэтому, когда класс вызывается, эти переменные или блоки выполняются.Поэтому большая часть инициализации будет выполняться с помощью статического ключевого слова.Поскольку он принадлежит самому классу, класс может напрямую обращаться к нему, не создавая экземпляр класса.

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

Пример:

    class Shoe {
    int size;
    String colour;
    static String brand = "Nike";

    public Shoe(int size, String colour) {
        super();
        this.size = size;
        this.colour = colour;
    }

    void displayShoe() {
        System.out.printf("%-2d %-8s %s %n",size,colour, brand);
    }

    public static void main(String args[]) {
        Shoe s1 = new Shoe(7, "Blue");
        Shoe s2 = new Shoe(8, "White");

        System.out.println("=================");
        s1.displayShoe();
        s2.displayShoe();
        System.out.println("=================");
    }
}
0 голосов
/ 04 апреля 2018

Мы используем конструкторы для инициализации переменных нашего экземпляра (нестатические переменные, переменные, принадлежащие объектам, а не классу).

Если вы хотите инициализировать переменные класса (статические переменные) и хотите сделать это без создания объекта (конструкторы можно вызывать только при создании объекта), то вам нужны статические блоки.

static Scanner input = new Scanner(System.in);
static int widht;
static int height;

static
{
    widht = input.nextInt();
    input.nextLine();
    height = input.nextInt();
    input.close();

    if ((widht < 0) || (height < 0))
    {
        System.out.println("java.lang.Exception: Width and height must be positive");
    }
    else
    {
        System.out.println("widht * height");
    }
}
...