Вопрос-ответ

What is the difference between a static and a non-static initialization code block

В чем разница между статическим и нестатическим блоками кода инициализации

Мой вопрос касается одного конкретного использования ключевого слова static. Можно использовать static ключевое слово для покрытия блока кода внутри класса, который не принадлежит ни одной функции. Например, следующий код компилируется:

public class Test {
private static final int a;
static {
a = 5;
doSomething(a);
}
private static int doSomething(int x) {
return (x+5);
}
}

Если вы удалите static ключевое слово, оно будет жаловаться, потому что переменная a является final. Однако можно удалить оба final и static ключевые слова и заставить его компилироваться.

Меня это сбивает с толку обоими способами. Откуда у меня должен быть раздел кода, который не принадлежит ни одному методу? Как его можно вызвать? В общем, какова цель такого использования? Или лучше, где я могу найти документацию по этому поводу?

Переведено автоматически
Ответ 1

Блок кода со статическим модификатором обозначает инициализатор класса; без статического модификатора блок кода является инициализатором экземпляра.

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

Инициализаторы экземпляра выполняются в порядке, определенном при создании экземпляра класса, непосредственно перед выполнением кода конструктора, сразу после вызова суперконструктора.

Если вы удалите static из int a, это станет переменной экземпляра, к которой вы не сможете получить доступ из блока статического инициализатора. При этом произойдет сбой компиляции с ошибкой "на нестатическую переменную a нельзя ссылаться из статического контекста".

Если вы также удалите static из блока инициализатора, он затем становится инициализатором экземпляра и, таким образом, int a инициализируется при построении.

Ответ 2

Уф! что такое статический инициализатор?

Статический инициализатор представляет собой static {} блок кода внутри класса java и выполняется только один раз перед вызовом конструктора или метода main.

ХОРОШО! Расскажите мне больше...


  • это блок кода static { ... } внутри любого класса Java. и выполняется виртуальной машиной при вызове класса.

  • Операторы return не поддерживаются.

  • Аргументы не поддерживаются.

  • Не this или super поддерживаются.

Хм, где я могу это использовать?

Может использоваться везде, где вам удобно :) вот так просто. Но я вижу, что большую часть времени он используется при подключении к базе данных, инициализации API, ведении журнала и т.д.

Не лайте просто так! где пример?

package com.example.learnjava;

import java.util.ArrayList;

public class Fruit {

static {
System.out.println("Inside Static Initializer.");

// fruits array
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Orange");
fruits.add("Pear");

// print fruits
for (String fruit : fruits) {
System.out.println(fruit);
}
System.out.println("End Static Initializer.\n");
}

public static void main(String[] args) {
System.out.println("Inside Main Method.");
}
}

Вывод???


Внутри статического инициализатора.


Apple


Оранжевый


Pear


Завершите статический инициализатор.


Внутри метода Main.


Ответ 3

static Блок является "статическим инициализатором".

Он автоматически вызывается при загрузке класса, и другого способа вызвать его нет (даже через отражение).

Лично я использовал его только при написании кода JNI:

class JNIGlue {
static {
System.loadLibrary("foo");
}
}
Ответ 4

Это напрямую из http://www.programcreek.com/2011/10/java-class-instance-initializers /

1. Порядок выполнения

Посмотрите на следующий класс, знаете ли вы, какой из них выполняется первым?

public class Foo {

//instance variable initializer
String s = "abc";

//constructor
public Foo() {
System.out.println("constructor called");
}

//static initializer
static {
System.out.println("static initializer called");
}

//instance initializer
{
System.out.println("instance initializer called");
}

public static void main(String[] args) {
new Foo();
new Foo();
}
}

Вывод:


вызывается статический инициализатор


вызывается инициализатор экземпляра


вызывается конструктор


вызывается инициализатор экземпляра


вызывается конструктор


2. Как работает инициализатор экземпляра Java?

Приведенный выше инициализатор экземпляра содержит инструкцию println . Чтобы понять, как это работает, мы можем рассматривать его как инструкцию присваивания переменной, например, b = 0 . Это может сделать его более понятным.

Вместо

int b = 0, вы могли бы написать

int b;
b = 0;

Следовательно, инициализаторы экземпляра и инициализаторы переменных экземпляра практически одинаковы.

3. Когда полезны инициализаторы экземпляра?

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


  1. Код инициализатора должен обрабатывать исключения

  2. Выполнять вычисления, которые не могут быть выражены с помощью инициализатора переменной экземпляра.

Конечно, такой код можно было бы написать в конструкторах. Но если бы класс имел несколько конструкторов, вам пришлось бы повторять код в каждом конструкторе.

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

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

Спасибо Derhein.

Также обратите внимание, что анонимные классы, реализующие интерфейсы [1], не имеют конструкторов. Следовательно, инициализаторы экземпляра необходимы для выполнения любых типов выражений во время построения.

java